mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
api/ui: externalize tabline
This commit is contained in:
parent
7e571bca5d
commit
88023d5123
@ -266,7 +266,11 @@ a dictionary with these (optional) keys:
|
|||||||
most 256 different colors).
|
most 256 different colors).
|
||||||
`popupmenu_external` Instead of drawing the completion popupmenu on
|
`popupmenu_external` Instead of drawing the completion popupmenu on
|
||||||
the grid, Nvim will send higher-level events to
|
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.
|
Defaults to false.
|
||||||
|
|
||||||
Nvim will then send msgpack-rpc notifications, with the method name "redraw"
|
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"]
|
["popupmenu_hide"]
|
||||||
The popupmenu is hidden.
|
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:
|
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||||
|
@ -69,6 +69,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height,
|
|||||||
ui->height = (int)height;
|
ui->height = (int)height;
|
||||||
ui->rgb = true;
|
ui->rgb = true;
|
||||||
ui->pum_external = false;
|
ui->pum_external = false;
|
||||||
|
ui->tabline_external = false;
|
||||||
ui->resize = remote_ui_resize;
|
ui->resize = remote_ui_resize;
|
||||||
ui->clear = remote_ui_clear;
|
ui->clear = remote_ui_clear;
|
||||||
ui->eol_clear = remote_ui_eol_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) {
|
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) {
|
if (value.type != kObjectTypeBoolean) {
|
||||||
api_set_error(error, kErrorTypeValidation, "rgb must be a Boolean");
|
api_set_error(error, kErrorTypeValidation, "rgb must be a Boolean");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ui->rgb = value.data.boolean;
|
ui->rgb = value.data.boolean;
|
||||||
} else if (strcmp(name.data, "popupmenu_external") == 0) {
|
} else if (strequal(name.data, "popupmenu_external")) {
|
||||||
if (value.type != kObjectTypeBoolean) {
|
if (value.type != kObjectTypeBoolean) {
|
||||||
api_set_error(error, kErrorTypeValidation,
|
api_set_error(error, kErrorTypeValidation,
|
||||||
"popupmenu_external must be a Boolean");
|
"popupmenu_external must be a Boolean");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ui->pum_external = value.data.boolean;
|
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 {
|
} else {
|
||||||
api_set_error(error, kErrorTypeValidation, "No such ui option");
|
api_set_error(error, kErrorTypeValidation, "No such ui option");
|
||||||
}
|
}
|
||||||
|
@ -132,6 +132,7 @@
|
|||||||
#include "nvim/version.h"
|
#include "nvim/version.h"
|
||||||
#include "nvim/window.h"
|
#include "nvim/window.h"
|
||||||
#include "nvim/os/time.h"
|
#include "nvim/os/time.h"
|
||||||
|
#include "nvim/api/private/helpers.h"
|
||||||
|
|
||||||
#define MB_FILLER_CHAR '<' /* character used when a double-width character
|
#define MB_FILLER_CHAR '<' /* character used when a double-width character
|
||||||
* doesn't fit. */
|
* doesn't fit. */
|
||||||
@ -6885,8 +6886,13 @@ static void draw_tabline(void)
|
|||||||
if (ScreenLines == NULL) {
|
if (ScreenLines == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
redraw_tabline = false;
|
|
||||||
|
|
||||||
|
if (ui_is_widget_external(kUITabline)) {
|
||||||
|
draw_tabline_ext();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
redraw_tabline = false;
|
||||||
|
|
||||||
if (tabline_height() < 1)
|
if (tabline_height() < 1)
|
||||||
return;
|
return;
|
||||||
@ -7027,6 +7033,34 @@ static void draw_tabline(void)
|
|||||||
redraw_tabline = FALSE;
|
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[].
|
* Get buffer name for "buf" into NameBuff[].
|
||||||
* Takes care of special buffer names and translates special characters.
|
* Takes care of special buffer names and translates special characters.
|
||||||
|
@ -110,6 +110,7 @@ UI *tui_start(void)
|
|||||||
ui->stop = tui_stop;
|
ui->stop = tui_stop;
|
||||||
ui->rgb = p_tgc;
|
ui->rgb = p_tgc;
|
||||||
ui->pum_external = false;
|
ui->pum_external = false;
|
||||||
|
ui->tabline_external = false;
|
||||||
ui->resize = tui_resize;
|
ui->resize = tui_resize;
|
||||||
ui->clear = tui_clear;
|
ui->clear = tui_clear;
|
||||||
ui->eol_clear = tui_eol_clear;
|
ui->eol_clear = tui_eol_clear;
|
||||||
|
@ -58,6 +58,10 @@ static int busy = 0;
|
|||||||
static int height, width;
|
static int height, width;
|
||||||
static int old_mode_idx = -1;
|
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
|
// UI_CALL invokes a function on all registered UI instances. The functions can
|
||||||
// have 0-5 arguments (configurable by SELECT_NTH).
|
// have 0-5 arguments (configurable by SELECT_NTH).
|
||||||
//
|
//
|
||||||
@ -167,17 +171,20 @@ void ui_refresh(void)
|
|||||||
|
|
||||||
int width = INT_MAX, height = INT_MAX;
|
int width = INT_MAX, height = INT_MAX;
|
||||||
bool pum_external = true;
|
bool pum_external = true;
|
||||||
|
bool tabline_external = true;
|
||||||
|
|
||||||
for (size_t i = 0; i < ui_count; i++) {
|
for (size_t i = 0; i < ui_count; i++) {
|
||||||
UI *ui = uis[i];
|
UI *ui = uis[i];
|
||||||
width = MIN(ui->width, width);
|
width = MIN(ui->width, width);
|
||||||
height = MIN(ui->height, height);
|
height = MIN(ui->height, height);
|
||||||
pum_external &= ui->pum_external;
|
pum_external &= ui->pum_external;
|
||||||
|
tabline_external &= ui->tabline_external;
|
||||||
}
|
}
|
||||||
|
|
||||||
row = col = 0;
|
row = col = 0;
|
||||||
screen_resize(width, height);
|
screen_resize(width, height);
|
||||||
pum_set_external(pum_external);
|
pum_set_external(pum_external);
|
||||||
|
ui_set_widget_external(kUITabline, tabline_external);
|
||||||
ui_mode_info_set();
|
ui_mode_info_set();
|
||||||
old_mode_idx = -1;
|
old_mode_idx = -1;
|
||||||
ui_cursor_shape();
|
ui_cursor_shape();
|
||||||
@ -557,3 +564,30 @@ void ui_cursor_shape(void)
|
|||||||
conceal_check_cursur_line();
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -8,6 +8,13 @@
|
|||||||
#include "api/private/defs.h"
|
#include "api/private/defs.h"
|
||||||
#include "nvim/buffer_defs.h"
|
#include "nvim/buffer_defs.h"
|
||||||
|
|
||||||
|
// values for externalized widgets
|
||||||
|
typedef enum {
|
||||||
|
kUITabline,
|
||||||
|
kUICmdline,
|
||||||
|
kUIWildmenu
|
||||||
|
} UIWidget;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool bold, underline, undercurl, italic, reverse;
|
bool bold, underline, undercurl, italic, reverse;
|
||||||
int foreground, background, special;
|
int foreground, background, special;
|
||||||
@ -16,7 +23,7 @@ typedef struct {
|
|||||||
typedef struct ui_t UI;
|
typedef struct ui_t UI;
|
||||||
|
|
||||||
struct ui_t {
|
struct ui_t {
|
||||||
bool rgb, pum_external;
|
bool rgb, pum_external, tabline_external;
|
||||||
int width, height;
|
int width, height;
|
||||||
void *data;
|
void *data;
|
||||||
void (*resize)(UI *ui, int rows, int columns);
|
void (*resize)(UI *ui, int rows, int columns);
|
||||||
|
@ -58,6 +58,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
|
|||||||
rv->ui = ui;
|
rv->ui = ui;
|
||||||
rv->bridge.rgb = ui->rgb;
|
rv->bridge.rgb = ui->rgb;
|
||||||
rv->bridge.pum_external = ui->pum_external;
|
rv->bridge.pum_external = ui->pum_external;
|
||||||
|
rv->bridge.tabline_external = ui->tabline_external;
|
||||||
rv->bridge.stop = ui_bridge_stop;
|
rv->bridge.stop = ui_bridge_stop;
|
||||||
rv->bridge.resize = ui_bridge_resize;
|
rv->bridge.resize = ui_bridge_resize;
|
||||||
rv->bridge.clear = ui_bridge_clear;
|
rv->bridge.clear = ui_bridge_clear;
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "nvim/syntax.h"
|
#include "nvim/syntax.h"
|
||||||
#include "nvim/terminal.h"
|
#include "nvim/terminal.h"
|
||||||
#include "nvim/undo.h"
|
#include "nvim/undo.h"
|
||||||
|
#include "nvim/ui.h"
|
||||||
#include "nvim/os/os.h"
|
#include "nvim/os/os.h"
|
||||||
|
|
||||||
|
|
||||||
@ -5223,6 +5224,9 @@ static void last_status_rec(frame_T *fr, int statusline)
|
|||||||
*/
|
*/
|
||||||
int tabline_height(void)
|
int tabline_height(void)
|
||||||
{
|
{
|
||||||
|
if (ui_is_widget_external(kUITabline)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
assert(first_tabpage);
|
assert(first_tabpage);
|
||||||
switch (p_stal) {
|
switch (p_stal) {
|
||||||
case 0: return 0;
|
case 0: return 0;
|
||||||
|
58
test/functional/ui/tabline_spec.lua
Normal file
58
test/functional/ui/tabline_spec.lua
Normal file
@ -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)
|
Loading…
Reference in New Issue
Block a user