From 1ccbd94beec5c1f5d91b0b084062afa7908dd69e Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Fri, 12 Dec 2014 16:05:52 -0300 Subject: [PATCH 01/30] test: Fix clear/eol_clear in screen.lua These functions need to operate on the current the scroll region. --- test/functional/ui/screen.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 8e7d1ed798..c8eea38386 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -185,12 +185,13 @@ function Screen:_handle_resize(width, height) end function Screen:_handle_clear() - self:_clear_block(1, self._height, 1, self._width) + self:_clear_block(self._scroll_region.top, self._scroll_region.bot, + self._scroll_region.left, self._scroll_region.right) end function Screen:_handle_eol_clear() local row, col = self._cursor.row, self._cursor.col - self:_clear_block(row, 1, col, self._width - col) + self:_clear_block(row, 1, col, self._scroll_region.right - col) end function Screen:_handle_cursor_goto(row, col) From fc8f7686905bf0441f4a2f35a65dad85fe813df3 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Fri, 12 Dec 2014 16:25:11 -0300 Subject: [PATCH 02/30] ui: Add update_fg/update_bg methods It is necessary to notify the UI when the default background/foreground colors change in order to render correctly. --- src/nvim/msgpack_rpc/remote_ui.c | 16 ++++++++++++++++ src/nvim/syntax.c | 3 +++ src/nvim/ui.c | 14 ++++++++++++++ src/nvim/ui.h | 2 ++ test/functional/ui/screen.lua | 8 ++++++++ 5 files changed, 43 insertions(+) diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c index f980a77b4c..af7b82dfd4 100644 --- a/src/nvim/msgpack_rpc/remote_ui.c +++ b/src/nvim/msgpack_rpc/remote_ui.c @@ -67,6 +67,8 @@ Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, Array args, ui->put = remote_ui_put; ui->bell = remote_ui_bell; ui->visual_bell = remote_ui_visual_bell; + ui->update_fg = remote_ui_update_fg; + ui->update_bg = remote_ui_update_bg; ui->flush = remote_ui_flush; ui->suspend = remote_ui_suspend; pmap_put(uint64_t)(connected_uis, channel_id, ui); @@ -266,6 +268,20 @@ static void remote_ui_visual_bell(UI *ui) push_call(ui, "visual_bell", args); } +static void remote_ui_update_fg(UI *ui, int fg) +{ + Array args = ARRAY_DICT_INIT; + ADD(args, INTEGER_OBJ(fg)); + push_call(ui, "update_fg", args); +} + +static void remote_ui_update_bg(UI *ui, int bg) +{ + Array args = ARRAY_DICT_INIT; + ADD(args, INTEGER_OBJ(bg)); + push_call(ui, "update_bg", args); +} + static void remote_ui_flush(UI *ui) { UIData *data = ui->data; diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index e9a814bc97..c03edc2cca 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -45,6 +45,7 @@ #include "nvim/strings.h" #include "nvim/syntax_defs.h" #include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/os/os.h" #include "nvim/os/time.h" @@ -6518,6 +6519,7 @@ do_highlight ( if (is_normal_group) { normal_fg = HL_TABLE()[idx].sg_rgb_fg; + ui_fg_updated(); } } else if (STRCMP(key, "GUIBG") == 0) { if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) { @@ -6536,6 +6538,7 @@ do_highlight ( if (is_normal_group) { normal_bg = HL_TABLE()[idx].sg_rgb_bg; + ui_bg_updated(); } } else if (STRCMP(key, "GUISP") == 0) { // Ignored diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 25d6a81960..afb281daba 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -113,6 +113,18 @@ void ui_write(uint8_t *s, int len) free(tofree); } +void ui_fg_updated(void) +{ + UI_CALL(update_fg, normal_fg); + UI_CALL(flush); +} + +void ui_bg_updated(void) +{ + UI_CALL(update_bg, normal_bg); + UI_CALL(flush); +} + /* * If the machine has job control, use it to suspend the program, * otherwise fake it by starting a new shell. @@ -167,6 +179,8 @@ void ui_cursor_shape(void) void ui_resize(int width, int height) { + ui_fg_updated(); + ui_bg_updated(); sr.top = 0; sr.bot = height - 1; sr.left = 0; diff --git a/src/nvim/ui.h b/src/nvim/ui.h index d0933055cc..7c4a233d79 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -32,6 +32,8 @@ struct ui_t { void (*bell)(UI *ui); void (*visual_bell)(UI *ui); void (*flush)(UI *ui); + void (*update_fg)(UI *ui, int fg); + void (*update_bg)(UI *ui, int bg); void (*suspend)(UI *ui); }; diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index c8eea38386..640d258c44 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -279,6 +279,14 @@ function Screen:_handle_visual_bell() self._visual_bell = true end +function Screen:_handle_update_fg(fg) + self._fg = fg +end + +function Screen:_handle_update_bg(bg) + self._bg = bg +end + function Screen:_handle_suspend() self._suspended = true end From 6c447848bb32784e10b2e8949eac12140bfb4a64 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Fri, 12 Dec 2014 16:26:27 -0300 Subject: [PATCH 03/30] ui: Increase cursor row when text being rendered would cross its limit --- src/nvim/ui.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/nvim/ui.c b/src/nvim/ui.c index afb281daba..c3b4788f43 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -458,6 +458,9 @@ static void parse_abstract_ui_codes(uint8_t *ptr, int len) UI_CALL(put, NULL, 0); col++; } + if (col >= width) { + ui_cursor_goto(row + 1, 0); + } p += clen; } ptr = p; From f0a944d3cf5d8f74f381cbf4fa8dc99cd99bca03 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Fri, 12 Dec 2014 16:27:54 -0300 Subject: [PATCH 04/30] ui: Add mising T_CSV code to abstract_ui termcap This code is required for screen.c to set a vertical scroll region, which is a great optimization when scrolling vertically split windows. --- src/nvim/term.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nvim/term.c b/src/nvim/term.c index b78b01b68a..c75f9272e3 100644 --- a/src/nvim/term.c +++ b/src/nvim/term.c @@ -170,6 +170,7 @@ static struct builtin_term builtin_termcaps[] = {(int)KS_DL, "\033|d"}, {(int)KS_CDL, "\033|%p1%dD"}, {(int)KS_CS, "\033|%p1%d;%p2%dR"}, + {(int)KS_CSV, "\033|%p1%d;%p2%dV"}, {(int)KS_CL, "\033|C"}, // attributes switched on with 'h', off with * 'H' {(int)KS_ME, "\033|31H"}, // HL_ALL From 8c12292a6129381dada53009ff90e4e22545f60b Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sat, 13 Dec 2014 09:20:00 -0300 Subject: [PATCH 05/30] remote_ui: Move handler registration to remote_ui.c Also disable deferral of attach_ui --- src/nvim/msgpack_rpc/channel.c | 7 ----- src/nvim/msgpack_rpc/remote_ui.c | 45 ++++++++++++++++++-------------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 4c35cce09a..f3c5a7a1e2 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -103,14 +103,7 @@ void channel_init(void) } if (abstract_ui) { - // Add handler for "attach_ui" remote_ui_init(); - String method = cstr_as_string("attach_ui"); - MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .defer = true}; - msgpack_rpc_add_method_handler(method, handler); - method = cstr_as_string("detach_ui"); - handler.fn = remote_ui_detach; - msgpack_rpc_add_method_handler(method, handler); } } diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c index af7b82dfd4..e27d4383c0 100644 --- a/src/nvim/msgpack_rpc/remote_ui.c +++ b/src/nvim/msgpack_rpc/remote_ui.c @@ -26,10 +26,32 @@ static PMap(uint64_t) *connected_uis = NULL; void remote_ui_init(void) { connected_uis = pmap_new(uint64_t)(); + // Add handler for "attach_ui" + String method = cstr_as_string("attach_ui"); + MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .defer = false}; + msgpack_rpc_add_method_handler(method, handler); + method = cstr_as_string("detach_ui"); + handler.fn = remote_ui_detach; + msgpack_rpc_add_method_handler(method, handler); } -Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, Array args, - Error *error) +void remote_ui_disconnect(uint64_t channel_id) +{ + UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); + if (!ui) { + return; + } + UIData *data = ui->data; + // destroy pending screen updates + api_free_array(data->buffer); + pmap_del(uint64_t)(connected_uis, channel_id); + free(ui->data); + ui_detach(ui); + free(ui); +} + +static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, + Array args, Error *error) { if (pmap_has(uint64_t)(connected_uis, channel_id)) { api_set_error(error, Exception, _("UI already attached for channel")); @@ -77,8 +99,8 @@ Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, Array args, return NIL; } -Object remote_ui_detach(uint64_t channel_id, uint64_t request_id, Array args, - Error *error) +static Object remote_ui_detach(uint64_t channel_id, uint64_t request_id, + Array args, Error *error) { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { api_set_error(error, Exception, _("UI is not attached for channel")); @@ -88,21 +110,6 @@ Object remote_ui_detach(uint64_t channel_id, uint64_t request_id, Array args, return NIL; } -void remote_ui_disconnect(uint64_t channel_id) -{ - UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); - if (!ui) { - return; - } - UIData *data = ui->data; - // destroy pending screen updates - api_free_array(data->buffer); - pmap_del(uint64_t)(connected_uis, channel_id); - free(ui->data); - ui_detach(ui); - free(ui); -} - static void push_call(UI *ui, char *name, Array args) { Array call = ARRAY_DICT_INIT; From 926503c84e694146f536b691f39e32857e57ac94 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sat, 13 Dec 2014 12:58:06 -0300 Subject: [PATCH 06/30] ui: Fix ui resizing and change some method names --- src/nvim/msgpack_rpc/remote_ui.c | 32 +++++++++++-- src/nvim/syntax.c | 6 ++- src/nvim/ui.c | 78 +++++++++++++------------------- test/functional/ui/screen.lua | 4 +- 4 files changed, 67 insertions(+), 53 deletions(-) diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c index e27d4383c0..a0bc573698 100644 --- a/src/nvim/msgpack_rpc/remote_ui.c +++ b/src/nvim/msgpack_rpc/remote_ui.c @@ -27,12 +27,15 @@ void remote_ui_init(void) { connected_uis = pmap_new(uint64_t)(); // Add handler for "attach_ui" - String method = cstr_as_string("attach_ui"); + String method = cstr_as_string("ui_attach"); MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .defer = false}; msgpack_rpc_add_method_handler(method, handler); - method = cstr_as_string("detach_ui"); + method = cstr_as_string("ui_detach"); handler.fn = remote_ui_detach; msgpack_rpc_add_method_handler(method, handler); + method = cstr_as_string("ui_try_resize"); + handler.fn = remote_ui_try_resize; + msgpack_rpc_add_method_handler(method, handler); } void remote_ui_disconnect(uint64_t channel_id) @@ -95,7 +98,6 @@ static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, ui->suspend = remote_ui_suspend; pmap_put(uint64_t)(connected_uis, channel_id, ui); ui_attach(ui); - return NIL; } @@ -110,6 +112,30 @@ static Object remote_ui_detach(uint64_t channel_id, uint64_t request_id, return NIL; } +static Object remote_ui_try_resize(uint64_t channel_id, uint64_t request_id, + Array args, Error *error) +{ + if (!pmap_has(uint64_t)(connected_uis, channel_id)) { + api_set_error(error, Exception, _("UI is not attached for channel")); + } + + if (args.size != 2 || args.items[0].type != kObjectTypeInteger + || args.items[1].type != kObjectTypeInteger + || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) { + api_set_error(error, Validation, + _("Arguments must be a pair of positive integers " + "representing the remote screen width/height")); + return NIL; + } + + UI *ui = pmap_get(uint64_t)(connected_uis, channel_id); + ui->width = (int)args.items[0].data.integer; + ui->height = (int)args.items[1].data.integer; + ui_refresh(); + return NIL; +} + + static void push_call(UI *ui, char *name, Array args) { Array call = ARRAY_DICT_INIT; diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index c03edc2cca..68eedecd50 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -6519,7 +6519,6 @@ do_highlight ( if (is_normal_group) { normal_fg = HL_TABLE()[idx].sg_rgb_fg; - ui_fg_updated(); } } else if (STRCMP(key, "GUIBG") == 0) { if (!init || !(HL_TABLE()[idx].sg_set & SG_GUI)) { @@ -6538,7 +6537,6 @@ do_highlight ( if (is_normal_group) { normal_bg = HL_TABLE()[idx].sg_rgb_bg; - ui_bg_updated(); } } else if (STRCMP(key, "GUISP") == 0) { // Ignored @@ -6635,6 +6633,10 @@ do_highlight ( if (is_normal_group) { HL_TABLE()[idx].sg_term_attr = 0; HL_TABLE()[idx].sg_cterm_attr = 0; + if (abstract_ui) { + // If the normal group has changed, it is simpler to refresh every UI + ui_refresh(); + } } else set_hl_attr(idx); HL_TABLE()[idx].sg_scriptID = current_SID; diff --git a/src/nvim/ui.c b/src/nvim/ui.c index c3b4788f43..042ca944a0 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -64,7 +64,7 @@ static HlAttrs current_attrs = { false, false, false, false, false, false, -1, -1 }; static bool cursor_enabled = true; -static int height = INT_MAX, width = INT_MAX; +static int height, width; // This set of macros allow us to use UI_CALL to invoke any function on // registered UI instances. The functions can have 0-5 arguments(configurable @@ -113,18 +113,6 @@ void ui_write(uint8_t *s, int len) free(tofree); } -void ui_fg_updated(void) -{ - UI_CALL(update_fg, normal_fg); - UI_CALL(flush); -} - -void ui_bg_updated(void) -{ - UI_CALL(update_bg, normal_bg); - UI_CALL(flush); -} - /* * If the machine has job control, use it to suspend the program, * otherwise fake it by starting a new shell. @@ -177,10 +165,36 @@ void ui_cursor_shape(void) } } -void ui_resize(int width, int height) +void ui_refresh(void) { - ui_fg_updated(); - ui_bg_updated(); + if (!ui_count) { + return; + } + + width = height = INT_MAX; + + for (size_t i = 0; i < ui_count; i++) { + UI *ui = uis[i]; + width = ui->width < width ? ui->width : width; + height = ui->height < height ? ui->height : height; + } + + screen_resize(width, height, true); +} + +void ui_resize(int new_width, int new_height) +{ + width = new_width; + height = new_height; + + if (normal_fg != -1) { + UI_CALL(update_fg, normal_fg); + } + + if (normal_bg != -1) { + UI_CALL(update_bg, normal_bg); + } + sr.top = 0; sr.bot = height - 1; sr.left = 0; @@ -254,7 +268,7 @@ void ui_attach(UI *ui) } uis[ui_count++] = ui; - resized(ui); + ui_refresh(); } void ui_detach(UI *ui) @@ -281,17 +295,8 @@ void ui_detach(UI *ui) ui_count--; - if (ui->width == width || ui->height == height) { - // It is possible that the UI being detached had the smallest screen, - // so check for the new minimum dimensions - width = height = INT_MAX; - for (size_t i = 0; i < ui_count; i++) { - check_dimensions(uis[i]); - } - } - if (ui_count) { - screen_resize(width, height, true); + ui_refresh(); } } @@ -474,25 +479,6 @@ static void parse_abstract_ui_codes(uint8_t *ptr, int len) UI_CALL(flush); } -static void resized(UI *ui) -{ - check_dimensions(ui); - screen_resize(width, height, true); -} - -static void check_dimensions(UI *ui) -{ - // The internal screen dimensions are always the minimum required to fit on - // all connected screens - if (ui->width < width) { - width = ui->width; - } - - if (ui->height < height) { - height = ui->height; - } -} - static void ui_linefeed(void) { int new_col = 0; diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 640d258c44..23ad66aeb6 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -115,12 +115,12 @@ function Screen:set_default_attr_ids(attr_ids) end function Screen:attach() - request('attach_ui', self._width, self._height) + request('ui_attach', self._width, self._height) self._suspended = false end function Screen:detach() - request('detach_ui') + request('ui_detach') self._suspended = true end From 17b211d288203ef394fc0dbf7b73a6cbf761921b Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sun, 14 Dec 2014 09:17:19 -0300 Subject: [PATCH 07/30] test: Remove unnecessary command from highlight_spec --- test/functional/ui/highlight_spec.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 3c55c09f95..9ab86f401f 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -142,7 +142,6 @@ describe('Default highlight groups', function() end) it('end of file markers', function() - nvim('command', 'hi Normal guibg=black') screen:expect([[ ^ | {1:~ }| From 3e83e44792021fb9d18acbb664172ce9a06dc9be Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sun, 14 Dec 2014 09:20:07 -0300 Subject: [PATCH 08/30] input: Ignore invalid "<" key sequences Ignoring invalid key sequences simplifies input handling in UIs. The only downside is having to use "" everytime a "<" is needed on functional tests. --- src/nvim/os/input.c | 10 ++++++++-- test/functional/legacy/066_visual_block_tab_spec.lua | 10 +++++----- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index c0d588f4ef..130e239a34 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -187,14 +187,20 @@ size_t input_enqueue(String keys) unsigned int new_size = trans_special((uint8_t **)&ptr, buf, false); if (!new_size) { + if (*ptr == '<') { + // Invalid key sequence, skip until the next '>' or until *end + do { + ptr++; + } while (ptr < end && *ptr != '>'); + ptr++; + continue; + } // copy the character unmodified *buf = (uint8_t)*ptr++; new_size = 1; } new_size = handle_mouse_event(&ptr, buf, new_size); - // TODO(tarruda): Don't produce past unclosed '<' characters, except if - // there's a lot of characters after the '<' rbuffer_write(input_buffer, (char *)buf, new_size); } diff --git a/test/functional/legacy/066_visual_block_tab_spec.lua b/test/functional/legacy/066_visual_block_tab_spec.lua index cd283e6746..82bb988c67 100644 --- a/test/functional/legacy/066_visual_block_tab_spec.lua +++ b/test/functional/legacy/066_visual_block_tab_spec.lua @@ -23,18 +23,18 @@ describe('visual block shift and tab characters', function() abcdefghijklmnopqrstuvwxyz]]) feed('gg') - feed([[fe4jRugvr1:'<,'>yank A]]) + feed([[fe4jRugvr1:','>yank A]]) execute('/^abcdefgh') - feed('4jI j<<11|D') + feed('4jI j11|D') feed('j7|a ') feed('j7|a ') - feed('j7|a 4k13|4j<') + feed('j7|a 4k13|4j') execute('$-5,$yank A') execute([[$-4,$s/\s\+//g]]) - feed('4kI j<<') + feed('4kI j') feed('j7|a ') feed('j7|a ') - feed('j7|a 4k13|4j3<') + feed('j7|a 4k13|4j3') execute('$-4,$yank A') -- Put @a and clean empty lines From 46b4764f7a484f7b0e032878389b8a7d92197129 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Tue, 30 Dec 2014 08:24:22 -0300 Subject: [PATCH 09/30] ui: Merge standout and reverse into one attribute --- src/nvim/msgpack_rpc/remote_ui.c | 4 ---- src/nvim/ui.c | 5 ++--- src/nvim/ui.h | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c index a0bc573698..e1cb474530 100644 --- a/src/nvim/msgpack_rpc/remote_ui.c +++ b/src/nvim/msgpack_rpc/remote_ui.c @@ -249,10 +249,6 @@ static void remote_ui_highlight_set(UI *ui, HlAttrs attrs) PUT(hl, "bold", BOOLEAN_OBJ(true)); } - if (attrs.standout) { - PUT(hl, "standout", BOOLEAN_OBJ(true)); - } - if (attrs.underline) { PUT(hl, "underline", BOOLEAN_OBJ(true)); } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 042ca944a0..424197ed77 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -61,7 +61,7 @@ static struct { } sr; static int current_highlight_mask = 0; static HlAttrs current_attrs = { - false, false, false, false, false, false, -1, -1 + false, false, false, false, false, -1, -1 }; static bool cursor_enabled = true; static int height, width; @@ -342,11 +342,10 @@ static void set_highlight_args(int mask, HlAttrs *attrs) } attrs->bold = mask & HL_BOLD; - attrs->standout = mask & HL_STANDOUT; attrs->underline = mask & HL_UNDERLINE; attrs->undercurl = mask & HL_UNDERCURL; attrs->italic = mask & HL_ITALIC; - attrs->reverse = mask & HL_INVERSE; + attrs->reverse = mask & (HL_INVERSE | HL_STANDOUT); attrs->foreground = aep && aep->fg_color >= 0 ? aep->fg_color : normal_fg; attrs->background = aep && aep->bg_color >= 0 ? aep->bg_color : normal_bg; } diff --git a/src/nvim/ui.h b/src/nvim/ui.h index 7c4a233d79..0fcd686e7b 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -6,7 +6,7 @@ #include typedef struct { - bool bold, standout, underline, undercurl, italic, reverse; + bool bold, underline, undercurl, italic, reverse; int foreground, background; } HlAttrs; From 631099d02abf2c5ceee88267622570df576b464c Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Fri, 2 Jan 2015 21:03:25 -0300 Subject: [PATCH 10/30] syntax: Take rgb fg/bg when allocating cterm attr number --- src/nvim/syntax.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 68eedecd50..c83968b7cc 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -7199,9 +7199,10 @@ set_hl_attr ( * For the color term mode: If there are other than "normal" * highlighting attributes, need to allocate an attr number. */ - if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0) + if (sgp->sg_cterm_fg == 0 && sgp->sg_cterm_bg == 0 + && sgp->sg_rgb_fg == -1 && sgp->sg_rgb_bg == -1) { sgp->sg_cterm_attr = sgp->sg_cterm; - else { + } else { at_en.ae_attr = abstract_ui ? sgp->sg_gui : sgp->sg_cterm; at_en.ae_u.cterm.fg_color = sgp->sg_cterm_fg; at_en.ae_u.cterm.bg_color = sgp->sg_cterm_bg; From 29bc6dfabde2c8881a719175f3d6cbf422ac72c0 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Thu, 8 Jan 2015 11:23:45 -0300 Subject: [PATCH 11/30] ui: Add 'rgb' parameter to ui_attach When set to false, nvim will send cterm color numbers with `highlight_set`. --- src/nvim/msgpack_rpc/remote_ui.c | 4 ++- src/nvim/syntax.c | 3 +- src/nvim/ui.c | 54 +++++++++++++++++++------------- src/nvim/ui.h | 1 + test/functional/ui/screen.lua | 2 +- 5 files changed, 38 insertions(+), 26 deletions(-) diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c index e1cb474530..6a638df61c 100644 --- a/src/nvim/msgpack_rpc/remote_ui.c +++ b/src/nvim/msgpack_rpc/remote_ui.c @@ -61,8 +61,9 @@ static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, return NIL; } - if (args.size != 2 || args.items[0].type != kObjectTypeInteger + if (args.size != 3 || args.items[0].type != kObjectTypeInteger || args.items[1].type != kObjectTypeInteger + || args.items[2].type != kObjectTypeBoolean || args.items[0].data.integer <= 0 || args.items[1].data.integer <= 0) { api_set_error(error, Validation, _("Arguments must be a pair of positive integers " @@ -75,6 +76,7 @@ static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, UI *ui = xcalloc(1, sizeof(UI)); ui->width = (int)args.items[0].data.integer; ui->height = (int)args.items[1].data.integer; + ui->rgb = args.items[2].data.boolean; ui->data = data; ui->resize = remote_ui_resize; ui->clear = remote_ui_clear; diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index c83968b7cc..14bca0c0d6 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -6439,8 +6439,7 @@ do_highlight ( HL_TABLE()[idx].sg_cterm &= ~HL_BOLD; } color &= 7; /* truncate to 8 colors */ - } else if (t_colors == 16 || t_colors == 88 - || t_colors == 256) { + } else if (t_colors == 16 || t_colors == 88 || t_colors == 256) { /* * Guess: if the termcap entry ends in 'm', it is * probably an xterm-like terminal. Use the changed diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 424197ed77..7ef9751241 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -60,9 +60,6 @@ static struct { int top, bot, left, right; } sr; static int current_highlight_mask = 0; -static HlAttrs current_attrs = { - false, false, false, false, false, -1, -1 -}; static bool cursor_enabled = true; static int height, width; @@ -187,13 +184,8 @@ void ui_resize(int new_width, int new_height) width = new_width; height = new_height; - if (normal_fg != -1) { - UI_CALL(update_fg, normal_fg); - } - - if (normal_bg != -1) { - UI_CALL(update_bg, normal_bg); - } + UI_CALL(update_fg, (ui->rgb ? normal_fg : cterm_normal_fg_color - 1)); + UI_CALL(update_bg, (ui->rgb ? normal_bg : cterm_normal_bg_color - 1)); sr.top = 0; sr.bot = height - 1; @@ -314,8 +306,7 @@ static void highlight_start(int mask) return; } - set_highlight_args(current_highlight_mask, ¤t_attrs); - UI_CALL(highlight_set, current_attrs); + set_highlight_args(current_highlight_mask); } static void highlight_stop(int mask) @@ -328,12 +319,12 @@ static void highlight_stop(int mask) current_highlight_mask &= ~mask; } - set_highlight_args(current_highlight_mask, ¤t_attrs); - UI_CALL(highlight_set, current_attrs); + set_highlight_args(current_highlight_mask); } -static void set_highlight_args(int mask, HlAttrs *attrs) +static void set_highlight_args(int mask) { + HlAttrs rgb_attrs = { false, false, false, false, false, -1, -1 }; attrentry_T *aep = NULL; if (mask > HL_ALL) { @@ -341,13 +332,32 @@ static void set_highlight_args(int mask, HlAttrs *attrs) mask = aep ? aep->ae_attr : 0; } - attrs->bold = mask & HL_BOLD; - attrs->underline = mask & HL_UNDERLINE; - attrs->undercurl = mask & HL_UNDERCURL; - attrs->italic = mask & HL_ITALIC; - attrs->reverse = mask & (HL_INVERSE | HL_STANDOUT); - attrs->foreground = aep && aep->fg_color >= 0 ? aep->fg_color : normal_fg; - attrs->background = aep && aep->bg_color >= 0 ? aep->bg_color : normal_bg; + rgb_attrs.bold = mask & HL_BOLD; + rgb_attrs.underline = mask & HL_UNDERLINE; + rgb_attrs.undercurl = mask & HL_UNDERCURL; + rgb_attrs.italic = mask & HL_ITALIC; + rgb_attrs.reverse = mask & (HL_INVERSE | HL_STANDOUT); + HlAttrs cterm_attrs = rgb_attrs; + + if (aep) { + if (aep->fg_color != normal_fg) { + rgb_attrs.foreground = aep->fg_color; + } + + if (aep->bg_color != normal_bg) { + rgb_attrs.background = aep->bg_color; + } + + if (cterm_normal_fg_color != aep->ae_u.cterm.fg_color) { + cterm_attrs.foreground = aep->ae_u.cterm.fg_color - 1; + } + + if (cterm_normal_bg_color != aep->ae_u.cterm.bg_color) { + cterm_attrs.background = aep->ae_u.cterm.bg_color - 1; + } + } + + UI_CALL(highlight_set, (ui->rgb ? rgb_attrs : cterm_attrs)); } static void parse_abstract_ui_codes(uint8_t *ptr, int len) diff --git a/src/nvim/ui.h b/src/nvim/ui.h index 0fcd686e7b..9ec10db75e 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -13,6 +13,7 @@ typedef struct { typedef struct ui_t UI; struct ui_t { + bool rgb; int width, height; void *data; void (*resize)(UI *ui, int rows, int columns); diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 23ad66aeb6..7e8811fe2f 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -115,7 +115,7 @@ function Screen:set_default_attr_ids(attr_ids) end function Screen:attach() - request('ui_attach', self._width, self._height) + request('ui_attach', self._width, self._height, true) self._suspended = false end From 5d2f923fcfce82996fd50c87d1ff015ba924468a Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Fri, 9 Jan 2015 09:07:58 -0300 Subject: [PATCH 12/30] channel: Free channels created from libuv streams --- src/nvim/msgpack_rpc/channel.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index f3c5a7a1e2..af7e7fa409 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -637,6 +637,7 @@ static void close_channel(Channel *channel) uv_handle_t *handle = (uv_handle_t *)channel->data.streams.uv; if (handle) { uv_close(handle, close_cb); + free_channel(channel); } else { event_push((Event) { .handler = on_stdio_close }, false); } From a282d06a678f2236e29d1dadb2a3f35f76c5ea3d Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Fri, 9 Jan 2015 09:18:23 -0300 Subject: [PATCH 13/30] ui: Don't parse abstract_ui codes if there are no attached UIs --- src/nvim/ui.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 7ef9751241..cb2f397dbb 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -362,6 +362,10 @@ static void set_highlight_args(int mask) static void parse_abstract_ui_codes(uint8_t *ptr, int len) { + if (!ui_count) { + return; + } + int arg1 = 0, arg2 = 0; uint8_t *end = ptr + len, *p, c; bool update_cursor = false; From 2db40492749ca7c20b42368a04729765e44eeda7 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Fri, 9 Jan 2015 09:51:11 -0300 Subject: [PATCH 14/30] ui: Fix `:suspend` command for remote UIs Forward the command to the remote UI and flush immediately. The semantics/handling is UI-specific. --- src/nvim/msgpack_rpc/remote_ui.c | 4 ++-- src/nvim/ui.c | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c index 6a638df61c..8350ae252b 100644 --- a/src/nvim/msgpack_rpc/remote_ui.c +++ b/src/nvim/msgpack_rpc/remote_ui.c @@ -322,6 +322,6 @@ static void remote_ui_flush(UI *ui) static void remote_ui_suspend(UI *ui) { - UIData *data = ui->data; - remote_ui_disconnect(data->channel_id); + Array args = ARRAY_DICT_INIT; + push_call(ui, "suspend", args); } diff --git a/src/nvim/ui.c b/src/nvim/ui.c index cb2f397dbb..3e5639d23e 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -119,6 +119,7 @@ void ui_suspend(void) { if (abstract_ui) { UI_CALL(suspend); + UI_CALL(flush); } else { mch_suspend(); } From df1f62194ea0f06bfe58eba9050fd633b790e0f2 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sat, 10 Jan 2015 01:30:31 -0300 Subject: [PATCH 15/30] channel: Make pending_requests a field of the Channel type This is required to send redraw notifications while a msgpack-rpc call is being performed by another channel. --- src/nvim/msgpack_rpc/channel.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index af7e7fa409..c8f8252e6d 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -45,6 +45,7 @@ typedef struct { typedef struct { uint64_t id; + size_t pending_requests; PMap(cstr_t) *subscribed_events; bool is_job, closed; msgpack_unpacker *unpacker; @@ -83,7 +84,6 @@ static uint64_t next_id = 1; static PMap(uint64_t) *channels = NULL; static PMap(cstr_t) *event_strings = NULL; static msgpack_sbuffer out_buffer; -static size_t pending_requests = 0; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "msgpack_rpc/channel.c.generated.h" @@ -193,20 +193,21 @@ bool channel_send_event(uint64_t id, char *name, Array args) return false; } - if (pending_requests) { - DelayedNotification p = { - .channel = channel, - .method = cstr_to_string(name), - .args = args - }; - // Pending request, queue the notification for sending later - *kl_pushp(DelayedNotification, delayed_notifications) = p; - } else { - if (channel) { - send_event(channel, name, args); + if (channel) { + if (channel->pending_requests) { + DelayedNotification p = { + .channel = channel, + .method = cstr_to_string(name), + .args = args + }; + // Pending request, queue the notification for sending later + *kl_pushp(DelayedNotification, delayed_notifications) = p; } else { - broadcast_event(name, args); + send_event(channel, name, args); } + } else { + // TODO(tarruda): Implement event broadcasting in vimscript + broadcast_event(name, args); } return true; @@ -239,10 +240,10 @@ Object channel_send_call(uint64_t id, // Push the frame ChannelCallFrame frame = {request_id, false, false, NIL}; kv_push(ChannelCallFrame *, channel->call_stack, &frame); - pending_requests++; + channel->pending_requests++; event_poll_until(-1, frame.returned); (void)kv_pop(channel->call_stack); - pending_requests--; + channel->pending_requests--; if (frame.errored) { api_set_error(err, Exception, "%s", frame.result.data.string.data); @@ -254,7 +255,7 @@ Object channel_send_call(uint64_t id, free_channel(channel); } - if (!pending_requests) { + if (!channel->pending_requests) { send_delayed_notifications(); } @@ -681,6 +682,7 @@ static Channel *register_channel(void) rv->closed = false; rv->unpacker = msgpack_unpacker_new(MSGPACK_UNPACKER_INIT_BUFFER_SIZE); rv->id = next_id++; + rv->pending_requests = 0; rv->subscribed_events = pmap_new(cstr_t)(); rv->next_request_id = 1; kv_init(rv->call_stack); From b4f516a36a5c15bd9a8722fea13101c0d06aa086 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sat, 10 Jan 2015 02:37:22 -0300 Subject: [PATCH 16/30] ui: Fix out_flush/ui_write behavior to always flush for abstract_ui --- src/nvim/term.c | 9 +++------ src/nvim/ui.c | 4 ++++ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/nvim/term.c b/src/nvim/term.c index c75f9272e3..a1e13cfeb7 100644 --- a/src/nvim/term.c +++ b/src/nvim/term.c @@ -1822,12 +1822,9 @@ static int out_pos = 0; /* number of chars in out_buf */ */ void out_flush(void) { - if (out_pos != 0) { - /* set out_pos to 0 before ui_write, to avoid recursiveness */ - int len = out_pos; - out_pos = 0; - ui_write(out_buf, len); - } + int len = out_pos; + out_pos = 0; + ui_write(out_buf, len); } /* diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 3e5639d23e..77ab948809 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -95,6 +95,10 @@ void ui_write(uint8_t *s, int len) return; } + if (!len) { + return; + } + char_u *tofree = NULL; if (output_conv.vc_type != CONV_NONE) { From dac1cee9076367b20273dfd2997cd5af60861f64 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sat, 10 Jan 2015 22:44:29 -0300 Subject: [PATCH 17/30] ui: Use ui_linefeed to handle line breaks correctly ui_linefeed will scroll the screen when it becomes full. This can happen when executing external commands. --- src/nvim/ui.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 77ab948809..914b04111e 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -482,7 +482,7 @@ static void parse_abstract_ui_codes(uint8_t *ptr, int len) col++; } if (col >= width) { - ui_cursor_goto(row + 1, 0); + ui_linefeed(); } p += clen; } From f3666e55a44b3f241a98c9509551e2d2bb7bae12 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Sun, 11 Jan 2015 11:17:16 -0300 Subject: [PATCH 18/30] shell: When executing command, use screen functions to display output By calling ui_write directly, the internal screen isn't updated and invalid bytes aren't handled, which breaks the abstract UI model. --- src/nvim/os/shell.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index d0f8442768..d481d6af56 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -24,7 +24,6 @@ #include "nvim/option_defs.h" #include "nvim/charset.h" #include "nvim/strings.h" -#include "nvim/ui.h" #define DYNAMIC_BUFFER_INIT {NULL, 0, 0} @@ -414,6 +413,7 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer, char *start = output; size_t off = 0; + int lastrow = (int)Rows - 1; while (off < remaining) { if (output[off] == NL) { // Insert the line @@ -421,10 +421,8 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer, if (to_buffer) { ml_append(curwin->w_cursor.lnum++, (char_u *)output, 0, false); } else { - // pending data from the output buffer has been flushed to the screen, - // safe to call ui_write directly - ui_write((char_u *)output, (int)off); - ui_write((char_u *)"\r\n", 2); + screen_del_lines(0, 0, 1, (int)Rows, true, NULL); + screen_puts_len((char_u *)output, (int)off, lastrow, 0, 0); } size_t skip = off + 1; output += skip; @@ -448,8 +446,8 @@ static size_t write_output(char *output, size_t remaining, bool to_buffer, // remember that the NL was missing curbuf->b_no_eol_lnum = curwin->w_cursor.lnum; } else { - ui_write((char_u *)output, (int)remaining); - ui_write((char_u *)"\r\n", 2); + screen_del_lines(0, 0, 1, (int)Rows, true, NULL); + screen_puts_len((char_u *)output, (int)remaining, lastrow, 0, 0); } output += remaining; } else if (to_buffer) { From 784bda07040bda16a2e004dcac39a5194d5053b1 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Mon, 12 Jan 2015 08:59:51 -0300 Subject: [PATCH 19/30] ui: Fix redraw bug caused by race conditions with remote clients Before sending a resize command to the UIs, flush the current output buffer to ensure no redraw commands for a screen with invalid size are processed. --- src/nvim/screen.c | 3 +++ src/nvim/term.c | 6 ++++++ src/nvim/ui.c | 2 +- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 52ded0aa49..5cfda13dbd 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -8188,6 +8188,9 @@ void screen_resize(int width, int height, int mustset) check_shellsize(); if (abstract_ui) { + // Clear the output buffer to ensure UIs don't receive redraw command meant + // for invalid screen sizes. + out_buf_clear(); ui_resize(width, height); } else { mch_set_shellsize(); diff --git a/src/nvim/term.c b/src/nvim/term.c index a1e13cfeb7..2dc4d68b19 100644 --- a/src/nvim/term.c +++ b/src/nvim/term.c @@ -1817,6 +1817,12 @@ void term_write(char_u *s, size_t len) static char_u out_buf[OUT_SIZE + 1]; static int out_pos = 0; /* number of chars in out_buf */ +// Clear the output buffer +void out_buf_clear(void) +{ + out_pos = 0; +} + /* * out_flush(): flush the output buffer */ diff --git a/src/nvim/ui.c b/src/nvim/ui.c index 914b04111e..ef0386e395 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -173,7 +173,7 @@ void ui_refresh(void) return; } - width = height = INT_MAX; + int width = INT_MAX, height = INT_MAX; for (size_t i = 0; i < ui_count; i++) { UI *ui = uis[i]; From 8f3e61a043f6b1a3b22d56029ff878e54299ec7c Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Mon, 12 Jan 2015 10:28:32 -0300 Subject: [PATCH 20/30] syntax: Refresh UI when the color scheme changes --- src/nvim/syntax.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 14bca0c0d6..efb449f037 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -6037,6 +6037,7 @@ int load_colors(char_u *name) apply_autocmds(EVENT_COLORSCHEME, name, curbuf->b_fname, FALSE, curbuf); recursive = FALSE; + ui_refresh(); return retval; } From 3e9c55b51b07fbde649f9e49d266cd0fc1121ad9 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Tue, 13 Jan 2015 08:38:38 -0300 Subject: [PATCH 21/30] main: Fix color schemes for abstract_ui - Set 't_Co' to 256 at startup. The value can be changed by the user for compatibility with terminals that are less capable. - `has('gui_running')` will return 1 if at least one rgb UI is attached. Even though these changes are hacky, they are necessary to make the transition to the new UI architecture smoother. --- src/nvim/eval.c | 5 ++++- src/nvim/main.c | 7 +++---- src/nvim/screen.c | 7 +++---- src/nvim/syntax.c | 8 ++++---- src/nvim/ui.c | 10 ++++++++++ 5 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index d60ce2de73..417efd52a1 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -76,6 +76,7 @@ #include "nvim/tag.h" #include "nvim/tempfile.h" #include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/mouse.h" #include "nvim/undo.h" #include "nvim/version.h" @@ -10023,6 +10024,8 @@ static void f_has(typval_T *argvars, typval_T *rettv) #endif } else if (STRICMP(name, "syntax_items") == 0) { n = syntax_present(curwin); + } else if (STRICMP(name, "gui_running") == 0) { + n = ui_rgb_attached(); } } @@ -14440,7 +14443,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv) if (modec != 't' && modec != 'c' && modec != 'g') modec = 0; /* replace invalid with current */ } else { - if (t_colors > 1) + if (abstract_ui || t_colors > 1) modec = 'c'; else modec = 't'; diff --git a/src/nvim/main.c b/src/nvim/main.c index f063cc1238..7ca26a6eba 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -261,10 +261,7 @@ int main(int argc, char **argv) if (params.want_full_screen && !silent_mode) { if (embedded_mode) { - // In embedded mode don't do terminal-related initializations, assume an - // initial screen size of 80x20 - full_screen = true; - screen_resize(80, 20, false); + // embedded mode implies abstract_ui termcapinit((uint8_t *)"abstract_ui"); } else { // set terminal name and get terminal capabilities (will set full_screen) @@ -278,7 +275,9 @@ int main(int argc, char **argv) event_init(); if (abstract_ui) { + full_screen = true; t_colors = 256; + T_CCO = (uint8_t *)"256"; } else { // Print a warning if stdout is not a terminal TODO(tarruda): Remove this // check once the new terminal UI is implemented diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 5cfda13dbd..7d29cc7e2d 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -6150,8 +6150,7 @@ void screen_fill(int start_row, int end_row, int start_col, int end_col, int c1, return; /* it's a "normal" terminal when not in a GUI or cterm */ - norm_term = ( - t_colors <= 1); + norm_term = (!abstract_ui && t_colors <= 1); for (row = start_row; row < end_row; ++row) { if (has_mbyte ) { @@ -6675,8 +6674,8 @@ static void linecopy(int to, int from, win_T *wp) */ int can_clear(char_u *p) { - return *p != NUL && (t_colors <= 1 - || cterm_normal_bg_color == 0 || *T_UT != NUL); + return abstract_ui || (*p != NUL && (t_colors <= 1 + || cterm_normal_bg_color == 0 || *T_UT != NUL)); } /* diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index efb449f037..8ff0c71f69 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -6450,7 +6450,7 @@ do_highlight ( p = T_CAF; else p = T_CSF; - if (*p != NUL && *(p + STRLEN(p) - 1) == 'm') + if (abstract_ui || (*p != NUL && *(p + STRLEN(p) - 1) == 'm')) switch (t_colors) { case 16: color = color_numbers_8[i]; @@ -6865,7 +6865,7 @@ int hl_combine_attr(int char_attr, int prim_attr) if (char_attr <= HL_ALL && prim_attr <= HL_ALL) return char_attr | prim_attr; - if (t_colors > 1) { + if (abstract_ui || t_colors > 1) { if (char_attr > HL_ALL) char_aep = syn_cterm_attr2entry(char_attr); if (char_aep != NULL) @@ -6929,7 +6929,7 @@ int syn_attr2attr(int attr) { attrentry_T *aep; - if (t_colors > 1) + if (abstract_ui || t_colors > 1) aep = syn_cterm_attr2entry(attr); else aep = syn_term_attr2entry(attr); @@ -7357,7 +7357,7 @@ int syn_id2attr(int hl_id) hl_id = syn_get_final_id(hl_id); sgp = &HL_TABLE()[hl_id - 1]; /* index is ID minus one */ - if (t_colors > 1) + if (abstract_ui || t_colors > 1) attr = sgp->sg_cterm_attr; else attr = sgp->sg_term_attr; diff --git a/src/nvim/ui.c b/src/nvim/ui.c index ef0386e395..d13c7e5feb 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -114,6 +114,16 @@ void ui_write(uint8_t *s, int len) free(tofree); } +bool ui_rgb_attached(void) +{ + for (size_t i = 0; i < ui_count; i++) { + if (uis[i]->rgb) { + return true; + } + } + return false; +} + /* * If the machine has job control, use it to suspend the program, * otherwise fake it by starting a new shell. From 6f7db326cb28d0746985952f765af48f3af21b10 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Tue, 13 Jan 2015 09:52:52 -0300 Subject: [PATCH 22/30] screen: Fix highlight reset for abstract_ui --- src/nvim/screen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 7d29cc7e2d..1eed8290f3 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -5971,7 +5971,7 @@ void screen_stop_highlight(void) */ void reset_cterm_colors(void) { - if (t_colors > 1) { + if (!abstract_ui && t_colors > 1) { /* set Normal cterm colors */ if (cterm_normal_fg_color > 0 || cterm_normal_bg_color > 0) { out_str(T_OP); From 8bff79d3fd76c849e871925fc5d9f1c3c8049031 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Tue, 13 Jan 2015 11:00:46 -0300 Subject: [PATCH 23/30] term: Fix shell_resized for abstract_ui --- src/nvim/term.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/nvim/term.c b/src/nvim/term.c index 2dc4d68b19..07b60e4573 100644 --- a/src/nvim/term.c +++ b/src/nvim/term.c @@ -2206,7 +2206,11 @@ void win_new_shellsize(void) */ void shell_resized(void) { - screen_resize(0, 0, FALSE); + if (abstract_ui) { + ui_refresh(); + } else { + screen_resize(0, 0, FALSE); + } } /* From ea771ac559054c138cda58e68daeb286f5c80e80 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Tue, 13 Jan 2015 18:05:57 -0300 Subject: [PATCH 24/30] test: Add Screen.debug for inspecting screens of hanging tests --- test/functional/ui/screen.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 7e8811fe2f..4163d8011a 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -83,6 +83,21 @@ local eq, dedent = helpers.eq, helpers.dedent local Screen = {} Screen.__index = Screen +local debug_screen + + +function Screen.debug(command) + if not command then + command = 'pynvim -n -g -c ' + end + command = command .. request('vim_eval', '$NVIM_LISTEN_ADDRESS') + if debug_screen then + debug_screen:close() + end + debug_screen = io.popen(command, 'r') + debug_screen:read() +end + function Screen.new(width, height) if not width then width = 53 From 8596776bf68f0e95ba3ff7b5176ef62b56f37f47 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Tue, 13 Jan 2015 21:19:59 -0300 Subject: [PATCH 25/30] ui: Implement set_{title,icon} --- src/nvim/msgpack_rpc/remote_ui.c | 16 ++++++++++++++++ src/nvim/os_unix.c | 13 +++++++++---- src/nvim/ui.c | 12 ++++++++++++ src/nvim/ui.h | 2 ++ test/functional/ui/screen.lua | 10 ++++++++++ 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/src/nvim/msgpack_rpc/remote_ui.c b/src/nvim/msgpack_rpc/remote_ui.c index 8350ae252b..361e93a6da 100644 --- a/src/nvim/msgpack_rpc/remote_ui.c +++ b/src/nvim/msgpack_rpc/remote_ui.c @@ -98,6 +98,8 @@ static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id, ui->update_bg = remote_ui_update_bg; ui->flush = remote_ui_flush; ui->suspend = remote_ui_suspend; + ui->set_title = remote_ui_set_title; + ui->set_icon = remote_ui_set_icon; pmap_put(uint64_t)(connected_uis, channel_id, ui); ui_attach(ui); return NIL; @@ -325,3 +327,17 @@ static void remote_ui_suspend(UI *ui) Array args = ARRAY_DICT_INIT; push_call(ui, "suspend", args); } + +static void remote_ui_set_title(UI *ui, char *title) +{ + Array args = ARRAY_DICT_INIT; + ADD(args, STRING_OBJ(cstr_to_string(title))); + push_call(ui, "set_title", args); +} + +static void remote_ui_set_icon(UI *ui, char *icon) +{ + Array args = ARRAY_DICT_INIT; + ADD(args, STRING_OBJ(cstr_to_string(icon))); + push_call(ui, "set_icon", args); +} diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 7ec4059bce..c4d0e9c592 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -43,6 +43,7 @@ #include "nvim/syntax.h" #include "nvim/tempfile.h" #include "nvim/term.h" +#include "nvim/ui.h" #include "nvim/types.h" #include "nvim/os/os.h" #include "nvim/os/time.h" @@ -181,22 +182,26 @@ void mch_settitle(char_u *title, char_u *icon) * Note: if "t_ts" is set, title is set with escape sequence rather * than x11 calls, because the x11 calls don't always work */ - if ((type || *T_TS != NUL) && title != NULL) { + if ((type || *T_TS != NUL || abstract_ui) && title != NULL) { if (oldtitle == NULL ) /* first call but not in GUI, save title */ (void)get_x11_title(FALSE); - if (*T_TS != NUL) /* it's OK if t_fs is empty */ + if (abstract_ui) { + ui_set_title((char *)title); + } else if (*T_TS != NUL) /* it's OK if t_fs is empty */ term_settitle(title); did_set_title = TRUE; } - if ((type || *T_CIS != NUL) && icon != NULL) { + if ((type || *T_CIS != NUL || abstract_ui) && icon != NULL) { if (oldicon == NULL ) /* first call, save icon */ get_x11_icon(FALSE); - if (*T_CIS != NUL) { + if (abstract_ui) { + ui_set_icon((char *)icon); + } else if (*T_CIS != NUL) { out_str(T_CIS); /* set icon start */ out_str_nf(icon); out_str(T_CIE); /* set icon end */ diff --git a/src/nvim/ui.c b/src/nvim/ui.c index d13c7e5feb..a8ca58d633 100644 --- a/src/nvim/ui.c +++ b/src/nvim/ui.c @@ -139,6 +139,18 @@ void ui_suspend(void) } } +void ui_set_title(char *title) +{ + UI_CALL(set_title, title); + UI_CALL(flush); +} + +void ui_set_icon(char *icon) +{ + UI_CALL(set_icon, icon); + UI_CALL(flush); +} + /* * Try to get the current Vim shell size. Put the result in Rows and Columns. * Use the new sizes as defaults for 'columns' and 'lines'. diff --git a/src/nvim/ui.h b/src/nvim/ui.h index 9ec10db75e..099f2643d5 100644 --- a/src/nvim/ui.h +++ b/src/nvim/ui.h @@ -36,6 +36,8 @@ struct ui_t { void (*update_fg)(UI *ui, int fg); void (*update_bg)(UI *ui, int bg); void (*suspend)(UI *ui); + void (*set_title)(UI *ui, char *title); + void (*set_icon)(UI *ui, char *icon); }; #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 4163d8011a..3a39cd0aa6 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -115,6 +115,8 @@ function Screen.new(width, height) _bell = false, _visual_bell = false, _suspended = true, + _title = nil, + _icon = nil, _attrs = {}, _cursor = { enabled = true, row = 1, col = 1 @@ -306,6 +308,14 @@ function Screen:_handle_suspend() self._suspended = true end +function Screen:_handle_set_title(title) + self._title = title +end + +function Screen:_handle_set_icon(icon) + self._icon = icon +end + function Screen:_clear_block(top, lines, left, columns) for i = top, top + lines - 1 do self:_clear_row_section(i, left, left + columns - 1) From 7b537ffda9751c1ec48fafae0f5b2a6bee29ad8b Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Wed, 14 Jan 2015 16:59:54 -0300 Subject: [PATCH 26/30] input: Read row/col position when processing mouse wheel --- src/nvim/os/input.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index 130e239a34..f04f0d8092 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -223,7 +223,8 @@ static unsigned int handle_mouse_event(char **ptr, uint8_t *buf, mouse_code = buf[5]; } - if (mouse_code < KE_LEFTMOUSE || mouse_code > KE_RIGHTRELEASE) { + if (!((mouse_code >= KE_LEFTMOUSE && mouse_code <= KE_RIGHTRELEASE) + || (mouse_code >= KE_MOUSEDOWN && mouse_code <= KE_MOUSERIGHT))) { return bufsize; } From 361c2290b6d8280c61d3e8193fa08f638f790da1 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Thu, 15 Jan 2015 08:58:14 -0300 Subject: [PATCH 27/30] input: Fix check for mouse coordinates Must check for EOF which will result in row/col being uninitialized. --- src/nvim/os/input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c index f04f0d8092..2ae4558f3d 100644 --- a/src/nvim/os/input.c +++ b/src/nvim/os/input.c @@ -233,7 +233,7 @@ static unsigned int handle_mouse_event(char **ptr, uint8_t *buf, // find mouse coordinates, and it would be too expensive to refactor this // now. int col, row, advance; - if (sscanf(*ptr, "<%d,%d>%n", &col, &row, &advance)) { + if (sscanf(*ptr, "<%d,%d>%n", &col, &row, &advance) != EOF && advance) { if (col >= 0 && row >= 0) { mouse_row = row; mouse_col = col; From c51c0950d3edef3309cf08979f5f9d434b8b73f0 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Thu, 15 Jan 2015 09:01:16 -0300 Subject: [PATCH 28/30] screen: Fix screen_resize to consider minimum screen size --- src/nvim/screen.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 1eed8290f3..8f4f894128 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -8185,6 +8185,8 @@ void screen_resize(int width, int height, int mustset) Columns = width; } check_shellsize(); + height = Rows; + width = Columns; if (abstract_ui) { // Clear the output buffer to ensure UIs don't receive redraw command meant From dc18fa256f335f2e8c7762a4d04e2efbc61d47cc Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Thu, 15 Jan 2015 09:01:25 -0300 Subject: [PATCH 29/30] test: Add more functional test to cover new code - emulate gui_running and terminal colors - scrolling/clearing regions - mouse wheel scrolling - setting icon/title - :stop/:suspend - screen resize --- test/functional/ui/highlight_spec.lua | 26 ++- test/functional/ui/mouse_spec.lua | 84 ++++++++ test/functional/ui/screen.lua | 81 ++++---- test/functional/ui/screen_basic_spec.lua | 254 +++++++++++++++++++++++ 4 files changed, 400 insertions(+), 45 deletions(-) diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 9ab86f401f..701297cc15 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -1,7 +1,30 @@ local helpers = require('test.functional.helpers') local Screen = require('test.functional.ui.screen') local clear, feed, nvim = helpers.clear, helpers.feed, helpers.nvim -local execute = helpers.execute +local execute, request, eq = helpers.execute, helpers.request, helpers.eq + + +describe('color scheme compatibility', function() + before_each(function() + clear() + end) + + it('t_Co is set to 256 by default', function() + eq('256', request('vim_eval', '&t_Co')) + request('vim_set_option', 't_Co', '88') + eq('88', request('vim_eval', '&t_Co')) + end) + + it('emulates gui_running when a rgb UI is attached', function() + eq(0, request('vim_eval', 'has("gui_running")')) + local screen = Screen.new() + screen:attach() + eq(1, request('vim_eval', 'has("gui_running")')) + screen:detach() + eq(0, request('vim_eval', 'has("gui_running")')) + end) +end) + describe('Default highlight groups', function() -- Test the default attributes for highlight groups shown by the :highlight @@ -24,7 +47,6 @@ describe('Default highlight groups', function() after_each(function() screen:detach() end) - it('window status bar', function() screen:set_default_attr_ids({ [1] = {reverse = true, bold = true}, -- StatusLine diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index 507b5aacae..653d8ad92c 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -1,6 +1,7 @@ local helpers = require('test.functional.helpers') local Screen = require('test.functional.ui.screen') local clear, feed, nvim = helpers.clear, helpers.feed, helpers.nvim +local insert, execute = helpers.insert, helpers.execute describe('Mouse input', function() local screen, hlgroup_colors @@ -154,4 +155,87 @@ describe('Mouse input', function() ]]) feed('') end) + + it('mouse whell will target the hovered window', function() + feed('ggdG') + insert([[ + Inserting + text + with + many + lines + to + test + mouse scrolling + ]]) + screen:try_resize(53, 14) + execute('sp', 'vsp') + screen:expect([[ + lines |lines | + to |to | + test |test | + mouse scrolling |mouse scrolling | + ^ | | + ~ |~ | + [No Name] [+] [No Name] [+] | + to | + test | + mouse scrolling | + | + ~ | + [No Name] [+] | + :vsp | + ]]) + feed('<0,0>') + screen:expect([[ + mouse scrolling |lines | + ^ |to | + ~ |test | + ~ |mouse scrolling | + ~ | | + ~ |~ | + [No Name] [+] [No Name] [+] | + to | + test | + mouse scrolling | + | + ~ | + [No Name] [+] | + | + ]]) + feed('<27,0>') + screen:expect([[ + mouse scrolling |text | + ^ |with | + ~ |many | + ~ |lines | + ~ |to | + ~ |test | + [No Name] [+] [No Name] [+] | + to | + test | + mouse scrolling | + | + ~ | + [No Name] [+] | + | + ]]) + feed('<27,7>') + screen:expect([[ + mouse scrolling |text | + ^ |with | + ~ |many | + ~ |lines | + ~ |to | + ~ |test | + [No Name] [+] [No Name] [+] | + Inserting | + text | + with | + many | + lines | + [No Name] [+] | + | + ]]) + end) end) diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua index 3a39cd0aa6..105e43843c 100644 --- a/test/functional/ui/screen.lua +++ b/test/functional/ui/screen.lua @@ -105,26 +105,22 @@ function Screen.new(width, height) if not height then height = 14 end - return setmetatable({ + local self = setmetatable({ + title = '', + icon = '', + bell = false, + visual_bell = false, + suspended = false, _default_attr_ids = nil, - _width = width, - _height = height, - _rows = new_cell_grid(width, height), _mode = 'normal', _mouse_enabled = true, - _bell = false, - _visual_bell = false, - _suspended = true, - _title = nil, - _icon = nil, _attrs = {}, _cursor = { enabled = true, row = 1, col = 1 - }, - _scroll_region = { - top = 1, bot = height, left = 1, right = width } }, Screen) + self:_handle_resize(width, height) + return self end function Screen:set_default_attr_ids(attr_ids) @@ -133,12 +129,14 @@ end function Screen:attach() request('ui_attach', self._width, self._height, true) - self._suspended = false end function Screen:detach() request('ui_detach') - self._suspended = true +end + +function Screen:try_resize(columns, rows) + request('ui_try_resize', columns, rows) end function Screen:expect(expected, attr_ids) @@ -151,7 +149,7 @@ function Screen:expect(expected, attr_ids) table.insert(expected_rows, row) end local ids = attr_ids or self._default_attr_ids - self:_wait(function() + self:wait(function() for i = 1, self._height do local expected_row = expected_rows[i] local actual_row = self:_row_repr(self._rows[i], ids) @@ -163,7 +161,7 @@ function Screen:expect(expected, attr_ids) end) end -function Screen:_wait(check, timeout) +function Screen:wait(check, timeout) local err, checked = false local function notification_cb(method, args) assert(method == 'redraw') @@ -198,7 +196,20 @@ function Screen:_redraw(updates) end function Screen:_handle_resize(width, height) - self._rows = new_cell_grid(width, height) + local rows = {} + for i = 1, height do + local cols = {} + for j = 1, width do + table.insert(cols, {text = ' ', attrs = {}}) + end + table.insert(rows, cols) + end + self._rows = rows + self._width = width + self._height = height + self._scroll_region = { + top = 1, bot = height, left = 1, right = width + } end function Screen:_handle_clear() @@ -268,11 +279,14 @@ function Screen:_handle_scroll(count) for i = start, stop, step do local target = self._rows[i] local source = self._rows[i + count] - self:_copy_row_section(target, source, left, right) + for j = left, right do + target[j].text = source[j].text + target[j].attrs = source[j].attrs + end end -- clear invalid rows - for i = stop + 1, stop + count, step do + for i = stop + step, stop + count, step do self:_clear_row_section(i, left, right) end end @@ -289,11 +303,11 @@ function Screen:_handle_put(str) end function Screen:_handle_bell() - self._bell = true + self.bell = true end function Screen:_handle_visual_bell() - self._visual_bell = true + self.visual_bell = true end function Screen:_handle_update_fg(fg) @@ -305,15 +319,15 @@ function Screen:_handle_update_bg(bg) end function Screen:_handle_suspend() - self._suspended = true + self.suspended = true end function Screen:_handle_set_title(title) - self._title = title + self.title = title end function Screen:_handle_set_icon(icon) - self._icon = icon + self.icon = icon end function Screen:_clear_block(top, lines, left, columns) @@ -330,13 +344,6 @@ function Screen:_clear_row_section(rownum, startcol, stopcol) end end -function Screen:_copy_row_section(target, source, startcol, stopcol) - for i = startcol, stopcol do - target[i].text = source[i].text - target[i].attrs = source[i].attrs - end -end - function Screen:_row_repr(row, attr_ids) local rv = {} local current_attr_id @@ -387,18 +394,6 @@ function backward_find_meaningful(tbl, from) return from end -function new_cell_grid(width, height) - local rows = {} - for i = 1, height do - local cols = {} - for j = 1, width do - table.insert(cols, {text = ' ', attrs = {}}) - end - table.insert(rows, cols) - end - return rows -end - function get_attr_id(attr_ids, attrs) if not attr_ids then return diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua index a1110b3231..4ee6c43528 100644 --- a/test/functional/ui/screen_basic_spec.lua +++ b/test/functional/ui/screen_basic_spec.lua @@ -16,6 +16,69 @@ describe('Screen', function() screen:detach() end) + describe(':suspend', function() + it('is forwarded to the UI', function() + local function check() + if not screen.suspended then + return 'Screen was not suspended' + end + end + execute('suspend') + screen:wait(check) + screen.suspended = false + feed('') + screen:wait(check) + end) + end) + + describe('bell/visual bell', function() + it('is forwarded to the UI', function() + feed('') + screen:wait(function() + if not screen.bell or screen.visual_bell then + return 'Bell was not sent' + end + end) + screen.bell = false + execute('set visualbell') + feed('') + screen:wait(function() + if not screen.visual_bell or screen.bell then + return 'Visual bell was not sent' + end + end) + end) + end) + + describe(':set title', function() + it('is forwarded to the UI', function() + local expected = 'test-title' + execute('set titlestring='..expected) + execute('set title') + screen:wait(function() + local actual = screen.title + if actual ~= expected then + return 'Expected title to be "'..expected..'" but was "'..actual..'"' + end + end) + end) + end) + + describe(':set icon', function() + it('is forwarded to the UI', function() + local expected = 'test-icon' + execute('set iconstring='..expected) + execute('set icon') + screen:wait(function() + local actual = screen.icon + if actual ~= expected then + return 'Expected title to be "'..expected..'" but was "'..actual..'"' + end + end) + end) + end) + + describe('window', function() describe('split', function() it('horizontal', function() @@ -95,6 +158,8 @@ describe('Screen', function() | ]]) end) + + end) end) @@ -221,4 +286,193 @@ describe('Screen', function() feed('') -- skip the "Press ENTER..." state or tests will hang end) end) + + describe('scrolling and clearing', function() + before_each(function() + insert([[ + Inserting + text + with + many + lines + to + test + scrolling + and + clearing + in + split + windows + ]]) + execute('sp', 'vsp', 'vsp') + screen:expect([[ + and |and |and | + clearing |clearing |clearing | + in |in |in | + split |split |split | + windows |windows |windows | + ^ | | | + [No Name] [+] [No Name] [+] [No Name] [+] | + clearing | + in | + split | + windows | + | + [No Name] [+] | + | + ]]) + end) + + it('only affects the current scroll region', function() + feed('6k') + screen:expect([[ + ^crolling |and |and | + and |clearing |clearing | + clearing |in |in | + in |split |split | + split |windows |windows | + windows | | | + [No Name] [+] [No Name] [+] [No Name] [+] | + clearing | + in | + split | + windows | + | + [No Name] [+] | + | + ]]) + feed('l') + screen:expect([[ + scrolling |and |and | + and |clearing |clearing | + clearing |in |in | + in |split |split | + split |windows |windows | + windows |^ | | + [No Name] [+] [No Name] [+] :ls') + screen:expect([[ + resize | + :ls^ | + ]]) + end) + end) end) From 14ebe608e2d26ba352f5abe1c32ce18fcc2eca06 Mon Sep 17 00:00:00 2001 From: Thiago de Arruda Date: Thu, 15 Jan 2015 09:01:44 -0300 Subject: [PATCH 30/30] deps: Update libtickit URL --- third-party/CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index debad7bf85..7c5906931d 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -73,9 +73,9 @@ set(LIBTERMKEY_URL https://github.com/neovim/libtermkey/archive/7b3bdafdf589d084 set(LIBTERMKEY_SHA1 28bfe54dfd9269910a132b51dee7725a2121578d) set(LIBTERMKEY_MD5 f0bac9c2467cc80c821be937ea5c13bc) -set(LIBTICKIT_URL https://github.com/neovim/libtickit/archive/0430ba2f43fdf1c31bca66def52a2537c581ade5.tar.gz) -set(LIBTICKIT_SHA1 732b145a4dab06e6f1b40a352424f808730726bf) -set(LIBTICKIT_MD5 3fcb635e572851472fc5009709d980fe) +set(LIBTICKIT_URL https://github.com/neovim/libtickit/archive/33f4afb3891df05955429acbf5b406dfe87ec22b.tar.gz) +set(LIBTICKIT_SHA1 3aab459b9fb3cd83e85ac2e08f05e5f162c8c9d2) +set(LIBTICKIT_MD5 19ee9271c16716620d0906db74158ec6) if(USE_BUNDLED_LIBUNIBILIUM) ExternalProject_Add(libunibilium