aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/msgpack_rpc.txt11
-rw-r--r--src/nvim/api/ui.c12
-rw-r--r--src/nvim/screen.c36
-rw-r--r--src/nvim/tui/tui.c1
-rw-r--r--src/nvim/ui.c34
-rw-r--r--src/nvim/ui.h9
-rw-r--r--src/nvim/ui_bridge.c1
-rw-r--r--src/nvim/window.c4
-rw-r--r--test/functional/ui/tabline_spec.lua58
9 files changed, 161 insertions, 5 deletions
diff --git a/runtime/doc/msgpack_rpc.txt b/runtime/doc/msgpack_rpc.txt
index 77cbc2f3d8..c550631a32 100644
--- a/runtime/doc/msgpack_rpc.txt
+++ b/runtime/doc/msgpack_rpc.txt
@@ -266,7 +266,11 @@ a dictionary with these (optional) keys:
most 256 different colors).
`popupmenu_external` Instead of drawing the completion popupmenu on
the grid, Nvim will send higher-level events to
- the ui and let it draw the popupmenu.
+ the UI and let it draw the popupmenu.
+ Defaults to false.
+ `tabline_external` Instead of drawing the tabline on the grid,
+ Nvim will send higher-level events to
+ the UI and let it draw the tabline.
Defaults to false.
Nvim will then send msgpack-rpc notifications, with the method name "redraw"
@@ -436,5 +440,10 @@ states might be represented as separate modes.
["popupmenu_hide"]
The popupmenu is hidden.
+["tabline_update", curtab, tabs]
+ Nvim will send this event when drawing tabline. curtab is the tab id
+ of the current tab. tabs is an arrays of the form:
+ [tabid, { "name": name }]
+
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index f0da0d1812..28fc641dec 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -69,6 +69,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
ui->height = (int)height;
ui->rgb = true;
ui->pum_external = false;
+ ui->tabline_external = false;
ui->resize = remote_ui_resize;
ui->clear = remote_ui_clear;
ui->eol_clear = remote_ui_eol_clear;
@@ -171,19 +172,26 @@ void nvim_ui_set_option(uint64_t channel_id, String name,
}
static void ui_set_option(UI *ui, String name, Object value, Error *error) {
- if (strcmp(name.data, "rgb") == 0) {
+ if (strequal(name.data, "rgb")) {
if (value.type != kObjectTypeBoolean) {
api_set_error(error, kErrorTypeValidation, "rgb must be a Boolean");
return;
}
ui->rgb = value.data.boolean;
- } else if (strcmp(name.data, "popupmenu_external") == 0) {
+ } else if (strequal(name.data, "popupmenu_external")) {
if (value.type != kObjectTypeBoolean) {
api_set_error(error, kErrorTypeValidation,
"popupmenu_external must be a Boolean");
return;
}
ui->pum_external = value.data.boolean;
+ } else if (strequal(name.data, "tabline_external")) {
+ if (value.type != kObjectTypeBoolean) {
+ api_set_error(error, kErrorTypeValidation,
+ "tabline_external must be a Boolean");
+ return;
+ }
+ ui->tabline_external = value.data.boolean;
} else {
api_set_error(error, kErrorTypeValidation, "No such ui option");
}
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 10dc86d5fa..ed85b6e8b8 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -132,6 +132,7 @@
#include "nvim/version.h"
#include "nvim/window.h"
#include "nvim/os/time.h"
+#include "nvim/api/private/helpers.h"
#define MB_FILLER_CHAR '<' /* character used when a double-width character
* doesn't fit. */
@@ -6885,8 +6886,13 @@ static void draw_tabline(void)
if (ScreenLines == NULL) {
return;
}
- redraw_tabline = false;
+ if (ui_is_widget_external(kUITabline)) {
+ draw_tabline_ext();
+ return;
+ }
+
+ redraw_tabline = false;
if (tabline_height() < 1)
return;
@@ -7027,6 +7033,34 @@ static void draw_tabline(void)
redraw_tabline = FALSE;
}
+// send tabline update to external ui
+void draw_tabline_ext(void)
+{
+ win_T *cwp;
+
+ Array args = ARRAY_DICT_INIT;
+ ADD(args, INTEGER_OBJ(curtab->handle));
+ Array tabs = ARRAY_DICT_INIT;
+ FOR_ALL_TABS(tp) {
+ if (tp == curtab) {
+ cwp = curwin;
+ } else {
+ cwp = tp->tp_curwin;
+ }
+ get_trans_bufname(cwp->w_buffer);
+ Array tab = ARRAY_DICT_INIT;
+ ADD(tab, INTEGER_OBJ(tp->handle));
+
+ Dictionary tab_info = ARRAY_DICT_INIT;
+ PUT(tab_info, "name", STRING_OBJ(cstr_to_string((char *)NameBuff)));
+ ADD(tab, DICTIONARY_OBJ(tab_info));
+ ADD(tabs, ARRAY_OBJ(tab));
+ }
+ ADD(args, ARRAY_OBJ(tabs));
+
+ ui_event("tabline_update", args);
+}
+
/*
* Get buffer name for "buf" into NameBuff[].
* Takes care of special buffer names and translates special characters.
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index e1b97f5306..cd94fe9d49 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -110,6 +110,7 @@ UI *tui_start(void)
ui->stop = tui_stop;
ui->rgb = p_tgc;
ui->pum_external = false;
+ ui->tabline_external = false;
ui->resize = tui_resize;
ui->clear = tui_clear;
ui->eol_clear = tui_eol_clear;
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 69916fa4cd..6dcc3de1b0 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -58,6 +58,10 @@ static int busy = 0;
static int height, width;
static int old_mode_idx = -1;
+static bool tabline_external = false;
+static bool cmdline_external = false;
+static bool wildmenu_external = false;
+
// UI_CALL invokes a function on all registered UI instances. The functions can
// have 0-5 arguments (configurable by SELECT_NTH).
//
@@ -167,17 +171,20 @@ void ui_refresh(void)
int width = INT_MAX, height = INT_MAX;
bool pum_external = true;
+ bool tabline_external = true;
for (size_t i = 0; i < ui_count; i++) {
UI *ui = uis[i];
width = MIN(ui->width, width);
height = MIN(ui->height, height);
pum_external &= ui->pum_external;
+ tabline_external &= ui->tabline_external;
}
row = col = 0;
screen_resize(width, height);
pum_set_external(pum_external);
+ ui_set_widget_external(kUITabline, tabline_external);
ui_mode_info_set();
old_mode_idx = -1;
ui_cursor_shape();
@@ -557,3 +564,30 @@ void ui_cursor_shape(void)
conceal_check_cursur_line();
}
+bool ui_is_widget_external(UIWidget widget)
+{
+ switch (widget) {
+ case kUITabline:
+ return tabline_external;
+ case kUICmdline:
+ return cmdline_external;
+ case kUIWildmenu:
+ return wildmenu_external;
+ }
+ return false;
+}
+
+void ui_set_widget_external(UIWidget widget, bool external)
+{
+ switch (widget) {
+ case kUITabline:
+ tabline_external = external;
+ break;
+ case kUICmdline:
+ cmdline_external = external;
+ break;
+ case kUIWildmenu:
+ wildmenu_external = external;
+ break;
+ }
+}
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index fcf52ac9e1..a1ff449eaf 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -8,6 +8,13 @@
#include "api/private/defs.h"
#include "nvim/buffer_defs.h"
+// values for externalized widgets
+typedef enum {
+ kUITabline,
+ kUICmdline,
+ kUIWildmenu
+} UIWidget;
+
typedef struct {
bool bold, underline, undercurl, italic, reverse;
int foreground, background, special;
@@ -16,7 +23,7 @@ typedef struct {
typedef struct ui_t UI;
struct ui_t {
- bool rgb, pum_external;
+ bool rgb, pum_external, tabline_external;
int width, height;
void *data;
void (*resize)(UI *ui, int rows, int columns);
diff --git a/src/nvim/ui_bridge.c b/src/nvim/ui_bridge.c
index 5697c765ba..9a3fcab13c 100644
--- a/src/nvim/ui_bridge.c
+++ b/src/nvim/ui_bridge.c
@@ -58,6 +58,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
rv->ui = ui;
rv->bridge.rgb = ui->rgb;
rv->bridge.pum_external = ui->pum_external;
+ rv->bridge.tabline_external = ui->tabline_external;
rv->bridge.stop = ui_bridge_stop;
rv->bridge.resize = ui_bridge_resize;
rv->bridge.clear = ui_bridge_clear;
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 60bba19b07..effce8b413 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -48,6 +48,7 @@
#include "nvim/syntax.h"
#include "nvim/terminal.h"
#include "nvim/undo.h"
+#include "nvim/ui.h"
#include "nvim/os/os.h"
@@ -5223,6 +5224,9 @@ static void last_status_rec(frame_T *fr, int statusline)
*/
int tabline_height(void)
{
+ if (ui_is_widget_external(kUITabline)) {
+ return 0;
+ }
assert(first_tabpage);
switch (p_stal) {
case 0: return 0;
diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua
new file mode 100644
index 0000000000..018e008e4a
--- /dev/null
+++ b/test/functional/ui/tabline_spec.lua
@@ -0,0 +1,58 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear, feed, eq = helpers.clear, helpers.feed, helpers.eq
+
+if helpers.pending_win32(pending) then return end
+
+describe('External tab line', function()
+ local screen
+ local tabs, curtab
+
+ before_each(function()
+ clear()
+ screen = Screen.new(25, 5)
+ screen:attach({rgb=true, tabline_external=true})
+ screen:set_on_event_handler(function(name, data)
+ if name == "tabline_update" then
+ curtab, tabs = unpack(data)
+ end
+ end)
+ end)
+
+ after_each(function()
+ screen:detach()
+ end)
+
+ describe("'tabline'", function()
+ it('tabline', function()
+ local expected = {
+ {1, {['name'] = '[No Name]'}},
+ {2, {['name'] = '[No Name]'}},
+ }
+ feed(":tabnew<CR>")
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq(2, curtab)
+ eq(expected, tabs)
+ end)
+
+ feed(":tabNext<CR>")
+ screen:expect([[
+ ^ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], nil, nil, function()
+ eq(1, curtab)
+ eq(expected, tabs)
+ end)
+
+ end)
+ end)
+end)