Merge pull request #4817 from bfredl/remoteui

api: refactor remote ui to use API dispatch generation
This commit is contained in:
Justin M. Keyes 2016-05-27 20:58:14 -04:00
commit f5642a171f
10 changed files with 58 additions and 70 deletions

View File

@ -143,7 +143,7 @@ local pattern = concat(
lit(')'),
any_amount(concat( -- optional attributes
spaces,
lit('FUNC_ATTR_'),
lit('FUNC_'),
any_amount(aw),
one_or_no(concat( -- attribute argument
spaces,

View File

@ -35,7 +35,8 @@ c_proto = Ct(
Cg(c_type, 'return_type') * Cg(c_id, 'name') *
fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') *
Cg(Cc(false), 'async') *
(fill * Cg((P('FUNC_ATTR_ASYNC') * Cc(true)), 'async') ^ -1) *
(fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) *
(fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) *
fill * P(';')
)
grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1)
@ -62,8 +63,11 @@ for i = 1, #arg - 1 do
local input = io.open(full_path, 'rb')
local tmp = grammar:match(input:read('*all'))
for i = 1, #tmp do
functions[#functions + 1] = tmp[i]
local fn = tmp[i]
if fn.noexport then
goto continue
end
functions[#functions + 1] = tmp[i]
if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then
-- this function should receive the channel id
fn.receives_channel_id = true
@ -77,6 +81,7 @@ for i = 1, #arg - 1 do
-- for specifying errors
fn.parameters[#fn.parameters] = nil
end
::continue::
end
input:close()
end
@ -217,7 +222,7 @@ for i = 1, #functions do
if fn.receives_channel_id then
-- if the function receives the channel id, pass it as first argument
if #args > 0 then
if #args > 0 or fn.can_fail then
output:write('channel_id, '..call_args)
else
output:write('channel_id')

View File

@ -7,13 +7,12 @@
#include "nvim/ui.h"
#include "nvim/memory.h"
#include "nvim/map.h"
#include "nvim/msgpack_rpc/remote_ui.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "msgpack_rpc/remote_ui.c.generated.h"
# include "api/ui.c.generated.h"
#endif
typedef struct {
@ -24,21 +23,13 @@ typedef struct {
static PMap(uint64_t) *connected_uis = NULL;
void remote_ui_init(void)
FUNC_API_NOEXPORT
{
connected_uis = pmap_new(uint64_t)();
// Add handler for "attach_ui"
String method = cstr_as_string("ui_attach");
MsgpackRpcRequestHandler handler = {.fn = remote_ui_attach, .async = false};
msgpack_rpc_add_method_handler(method, handler);
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)
FUNC_API_NOEXPORT
{
UI *ui = pmap_get(uint64_t)(connected_uis, channel_id);
if (!ui) {
@ -49,34 +40,30 @@ void remote_ui_disconnect(uint64_t channel_id)
api_free_array(data->buffer);
pmap_del(uint64_t)(connected_uis, channel_id);
xfree(ui->data);
ui_detach(ui);
ui_detach_impl(ui);
xfree(ui);
}
static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id,
Array args, Error *error)
void ui_attach(uint64_t channel_id, Integer width, Integer height,
Boolean enable_rgb, Error *err)
{
if (pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(error, Exception, _("UI already attached for channel"));
return NIL;
api_set_error(err, Exception, _("UI already attached for channel"));
return;
}
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,
_("Invalid arguments. Expected: "
"(uint width > 0, uint height > 0, bool enable_rgb)"));
return NIL;
if (width <= 0 || height <= 0) {
api_set_error(err, Validation,
_("Expected width > 0 and height > 0"));
return;
}
UIData *data = xmalloc(sizeof(UIData));
data->channel_id = channel_id;
data->buffer = (Array)ARRAY_DICT_INIT;
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->width = (int)width;
ui->height = (int)height;
ui->rgb = enable_rgb;
ui->data = data;
ui->resize = remote_ui_resize;
ui->clear = remote_ui_clear;
@ -102,45 +89,38 @@ static Object remote_ui_attach(uint64_t channel_id, uint64_t request_id,
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;
ui_attach_impl(ui);
return;
}
static Object remote_ui_detach(uint64_t channel_id, uint64_t request_id,
Array args, Error *error)
void ui_detach(uint64_t channel_id, Error *err)
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(error, Exception, _("UI is not attached for channel"));
api_set_error(err, Exception, _("UI is not attached for channel"));
}
remote_ui_disconnect(channel_id);
return NIL;
}
static Object remote_ui_try_resize(uint64_t channel_id, uint64_t request_id,
Array args, Error *error)
Object ui_try_resize(uint64_t channel_id, Integer width,
Integer height, Error *err)
{
if (!pmap_has(uint64_t)(connected_uis, channel_id)) {
api_set_error(error, Exception, _("UI is not attached for channel"));
api_set_error(err, 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,
_("Invalid arguments. Expected: "
"(uint width > 0, uint height > 0)"));
if (width <= 0 || height <= 0) {
api_set_error(err, Validation,
_("Expected width > 0 and height > 0"));
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->width = (int)width;
ui->height = (int)height;
ui_refresh();
return NIL;
}
static void push_call(UI *ui, char *name, Array args)
{
Array call = ARRAY_DICT_INIT;
@ -297,7 +277,7 @@ static void remote_ui_highlight_set(UI *ui, HlAttrs attrs)
static void remote_ui_put(UI *ui, uint8_t *data, size_t size)
{
Array args = ARRAY_DICT_INIT;
String str = {.data = xmemdupz(data, size), .size = size};
String str = { .data = xmemdupz(data, size), .size = size };
ADD(args, STRING_OBJ(str));
push_call(ui, "put", args);
}

11
src/nvim/api/ui.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef NVIM_API_UI_H
#define NVIM_API_UI_H
#include <stdint.h>
#include "nvim/api/private/defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/ui.h.generated.h"
#endif
#endif // NVIM_API_UI_H

View File

@ -98,7 +98,7 @@ void vim_feedkeys(String keys, String mode, Boolean escape_csi)
/// @return The number of bytes actually written, which can be lower than
/// requested if the buffer becomes full.
Integer vim_input(String keys)
FUNC_ATTR_ASYNC
FUNC_API_ASYNC
{
return (Integer)input_enqueue(keys);
}
@ -618,7 +618,7 @@ Dictionary vim_get_color_map(void)
Array vim_get_api_info(uint64_t channel_id)
FUNC_ATTR_ASYNC
FUNC_API_ASYNC
{
Array rv = ARRAY_DICT_INIT;

View File

@ -179,7 +179,8 @@
#endif
#ifdef DEFINE_FUNC_ATTRIBUTES
#define FUNC_ATTR_ASYNC
#define FUNC_API_ASYNC
#define FUNC_API_NOEXPORT
#define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC
#define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x)
#define FUNC_ATTR_ALLOC_SIZE_PROD(x,y) REAL_FATTR_ALLOC_SIZE_PROD(x,y)

View File

@ -7,8 +7,8 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
#include "nvim/api/ui.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/remote_ui.h"
#include "nvim/event/loop.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/rstream.h"

View File

@ -1,9 +0,0 @@
#ifndef NVIM_MSGPACK_RPC_REMOTE_UI_H
#define NVIM_MSGPACK_RPC_REMOTE_UI_H
#include "nvim/ui.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "msgpack_rpc/remote_ui.h.generated.h"
#endif
#endif // NVIM_MSGPACK_RPC_REMOTE_UI_H

View File

@ -207,7 +207,7 @@ void ui_mouse_off(void)
UI_CALL(mouse_off);
}
void ui_attach(UI *ui)
void ui_attach_impl(UI *ui)
{
if (ui_count == MAX_UI_COUNT) {
abort();
@ -217,7 +217,7 @@ void ui_attach(UI *ui)
ui_refresh();
}
void ui_detach(UI *ui)
void ui_detach_impl(UI *ui)
{
size_t shift_index = MAX_UI_COUNT;

View File

@ -71,7 +71,7 @@ UI *ui_bridge_attach(UI *ui, ui_main_fn ui_main, event_scheduler scheduler)
}
uv_mutex_unlock(&rv->mutex);
ui_attach(&rv->bridge);
ui_attach_impl(&rv->bridge);
return &rv->bridge;
}
@ -105,7 +105,7 @@ static void ui_bridge_stop(UI *b)
uv_thread_join(&bridge->ui_thread);
uv_mutex_destroy(&bridge->mutex);
uv_cond_destroy(&bridge->cond);
ui_detach(b);
ui_detach_impl(b);
xfree(b);
}
static void ui_bridge_stop_event(void **argv)