summaryrefslogtreecommitdiffstats
path: root/development/eovim/07716.patch
diff options
context:
space:
mode:
author Benjamin Trigona-Harany <slackbuilds@jaxartes.net>2019-12-15 23:31:29 -0800
committer Willy Sudiarto Raharjo <willysr@slackbuilds.org>2019-12-21 11:02:48 +0700
commit6ac16eacb19a96ca5f2aaf0e5d254a497d20e092 (patch)
tree73bdf60dd1d8b101979eb843ffda747681479492 /development/eovim/07716.patch
parentf2f1c84835f5161c48d4b4a8e2e77cca7db18711 (diff)
downloadslackbuilds-6ac16eacb19a96ca5f2aaf0e5d254a497d20e092.tar.gz
slackbuilds-6ac16eacb19a96ca5f2aaf0e5d254a497d20e092.tar.xz
development/eovim: Updated for version 0.1.3.
Signed-off-by: Benjamin Trigona-Harany <slackbuilds@jaxartes.net>
Diffstat (limited to 'development/eovim/07716.patch')
-rw-r--r--development/eovim/07716.patch427
1 files changed, 427 insertions, 0 deletions
diff --git a/development/eovim/07716.patch b/development/eovim/07716.patch
new file mode 100644
index 0000000000..a591038ac9
--- /dev/null
+++ b/development/eovim/07716.patch
@@ -0,0 +1,427 @@
+From 0771672b18c6645a7fa4de61ac106bdf3b69a04a Mon Sep 17 00:00:00 2001
+From: Jean Guyomarc'h <jean@guyomarch.bzh>
+Date: Sat, 12 Jan 2019 08:43:01 +0100
+Subject: [PATCH] nvim: handle requests initiates by neovim
+
+Neovim is able to initiate requests to the UI client (via the
+'rpcrequest()') API. Eovim is now able to run a user-defined callback
+function when a request is emitted. A request response is sent back to
+neovim. This is one step to solve #38.
+---
+ CMakeLists.txt | 1 +
+ include/eovim/nvim.h | 11 +++
+ include/eovim/nvim_request.h | 52 ++++++++++++++
+ src/main.c | 2 +
+ src/nvim.c | 72 +++++++++++++++++++-
+ src/nvim_api.c | 18 ++---
+ src/nvim_request.c | 127 +++++++++++++++++++++++++++++++++++
+ 7 files changed, 272 insertions(+), 11 deletions(-)
+ create mode 100644 include/eovim/nvim_request.h
+ create mode 100644 src/nvim_request.c
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index adf75dc..cfc6dbf 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -115,6 +115,7 @@ add_executable(eovim
+ "${SRC_DIR}/event/cmdline.c"
+ "${SRC_DIR}/nvim_api.c"
+ "${SRC_DIR}/nvim_helper.c"
++ "${SRC_DIR}/nvim_request.c"
+ "${SRC_DIR}/plugin.c"
+ "${SRC_DIR}/options.c"
+ "${SRC_DIR}/contrib.c"
+diff --git a/include/eovim/nvim.h b/include/eovim/nvim.h
+index 13c77ab..f27e3f4 100644
+--- a/include/eovim/nvim.h
++++ b/include/eovim/nvim.h
+@@ -52,6 +52,8 @@ struct nvim
+ Eina_List *requests;
+
+ msgpack_unpacker unpacker;
++
++ /* The following msgpack structures must be handled on the main loop only */
+ msgpack_sbuffer sbuffer;
+ msgpack_packer packer;
+ uint32_t request_id;
+@@ -76,4 +78,13 @@ void nvim_mouse_enabled_set(s_nvim *nvim, Eina_Bool enable);
+ Eina_Bool nvim_mouse_enabled_get(const s_nvim *nvim);
+ Eina_Stringshare *nvim_eovimrc_path_get(const s_nvim *nvim);
+
++/**
++ * Flush the msgpack buffer to the neovim instance, by writing to its standard
++ * input
++ *
++ * @param[in] nvim The neovim handle
++ * @return EINA_TRUE on success, EINA_FALSE on failure.
++ */
++Eina_Bool nvim_flush(s_nvim *nvim);
++
+ #endif /* ! __EOVIM_NVIM_H__ */
+diff --git a/include/eovim/nvim_request.h b/include/eovim/nvim_request.h
+new file mode 100644
+index 0000000..68de980
+--- /dev/null
++++ b/include/eovim/nvim_request.h
+@@ -0,0 +1,52 @@
++/*
++ * Copyright (c) 2019 Jean Guyomarc'h
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#ifndef EOVIM_NVIM_REQUEST_H__
++#define EOVIM_NVIM_REQUEST_H__
++
++#include "eovim/types.h"
++
++/**
++ * Callback signature used when replying to a request.
++ *
++ * @param[in] nvim The neovim handle
++ * @param[in] args Array of arguments from the request
++ * @param[in,out] pk Msgpack packer to be used to write the error and the
++ * result of the request. See msgpack-rpc.
++ * @return EINA_TRUE on success, EINA_FALSE on failure
++ *
++ * @note This function should not call nvim_flush(). It is automatically handled.
++ */
++typedef Eina_Bool (*f_nvim_request_cb)(s_nvim *nvim, const msgpack_object_array *args,
++ msgpack_packer *pk);
++
++Eina_Bool nvim_request_init(void);
++void nvim_request_shutdown(void);
++
++Eina_Bool nvim_request_add(const char *request_name, f_nvim_request_cb func);
++void nvim_request_del(const char *request_name);
++
++Eina_Bool
++nvim_request_process(s_nvim *nvim, Eina_Stringshare *request,
++ const msgpack_object_array *args, uint32_t req_id);
++
++#endif /* ! EOVIM_NVIM_REQUEST_H__ */
+diff --git a/src/main.c b/src/main.c
+index 2708186..4beb699 100644
+--- a/src/main.c
++++ b/src/main.c
+@@ -24,6 +24,7 @@
+ #include "eovim/config.h"
+ #include "eovim/nvim.h"
+ #include "eovim/nvim_api.h"
++#include "eovim/nvim_request.h"
+ #include "eovim/nvim_event.h"
+ #include "eovim/termview.h"
+ #include "eovim/main.h"
+@@ -53,6 +54,7 @@ static const s_module _modules[] =
+ MODULE(config),
+ MODULE(keymap),
+ MODULE(nvim_api),
++ MODULE(nvim_request),
+ MODULE(nvim_event),
+ MODULE(plugin),
+ MODULE(prefs),
+diff --git a/src/nvim.c b/src/nvim.c
+index 6c9d18f..83fdee4 100644
+--- a/src/nvim.c
++++ b/src/nvim.c
+@@ -26,6 +26,7 @@
+ #include "eovim/config.h"
+ #include "eovim/nvim_api.h"
+ #include "eovim/nvim_event.h"
++#include "eovim/nvim_request.h"
+ #include "eovim/nvim_helper.h"
+ #include "eovim/log.h"
+ #include "eovim/main.h"
+@@ -53,6 +54,51 @@ _nvim_get(void)
+ return _nvim_instance;
+ }
+
++static Eina_Bool
++_handle_request(s_nvim *nvim, const msgpack_object_array *args)
++{
++ /* Retrieve the request identifier ****************************************/
++ if (EINA_UNLIKELY(args->ptr[1].type != MSGPACK_OBJECT_POSITIVE_INTEGER))
++ {
++ ERR("Second argument in request is expected to be an integer");
++ return EINA_FALSE;
++ }
++ const uint64_t long_req_id = args->ptr[1].via.u64;
++ if (EINA_UNLIKELY(long_req_id > UINT32_MAX))
++ {
++ ERR("Request ID '%" PRIu64 " is too big", long_req_id);
++ return EINA_FALSE;
++ }
++ const uint32_t req_id = (uint32_t)long_req_id;
++
++ /* Retrieve the request arguments *****************************************/
++ if (EINA_UNLIKELY(args->ptr[3].type != MSGPACK_OBJECT_ARRAY))
++ {
++ ERR("Fourth argument in request is expected to be an array");
++ return EINA_FALSE;
++ }
++ const msgpack_object_array *const req_args = &(args->ptr[3].via.array);
++
++ /* Retrieve the request name **********************************************/
++ if (EINA_UNLIKELY(args->ptr[2].type != MSGPACK_OBJECT_STR))
++ {
++ ERR("Third argument in request is expected to be a string");
++ return EINA_FALSE;
++ }
++ const msgpack_object_str *const str = &(args->ptr[2].via.str);
++ Eina_Stringshare *const request =
++ eina_stringshare_add_length(str->ptr, str->size);
++ if (EINA_UNLIKELY(! request))
++ {
++ ERR("Failed to create stringshare");
++ return EINA_FALSE;
++ }
++
++ const Eina_Bool ok = nvim_request_process(nvim, request, req_args, req_id);
++ eina_stringshare_del(request);
++ return ok;
++}
++
+ static Eina_Bool
+ _handle_request_response(s_nvim *nvim,
+ const msgpack_object_array *args)
+@@ -289,6 +335,7 @@ _nvim_received_data_cb(void *data EINA_UNUSED,
+ int type EINA_UNUSED,
+ void *event)
+ {
++ /* See https://github.com/msgpack-rpc/msgpack-rpc/blob/master/spec.md */
+ const Ecore_Exe_Event_Data *const info = event;
+ s_nvim *const nvim = _nvim_get();
+ msgpack_unpacker *const unpacker = &nvim->unpacker;
+@@ -356,11 +403,15 @@ _nvim_received_data_cb(void *data EINA_UNUSED,
+ }
+ switch (args->ptr[0].via.u64)
+ {
+- case 1:
++ case 0: /* msgpack-rpc request */
++ _handle_request(nvim, args);
++ break;
++
++ case 1: /* msgpack-rpc response */
+ _handle_request_response(nvim, args);
+ break;
+
+- case 2:
++ case 2: /* msgpack-rpc notification */
+ _handle_notification(nvim, args);
+ break;
+
+@@ -824,6 +875,23 @@ nvim_free(s_nvim *nvim)
+ }
+ }
+
++Eina_Bool nvim_flush(s_nvim *nvim)
++{
++ /* Send the data present in the msgpack buffer */
++ const Eina_Bool ok =
++ ecore_exe_send(nvim->exe, nvim->sbuffer.data, (int)nvim->sbuffer.size);
++
++ /* Now that the data is gone (hopefully), clear the buffer */
++ msgpack_sbuffer_clear(&nvim->sbuffer);
++ if (EINA_UNLIKELY(! ok))
++ {
++ CRI("Failed to send %zu bytes to neovim", nvim->sbuffer.size);
++ return EINA_FALSE;
++ }
++ DBG("Sent %zu bytes to neovim", nvim->sbuffer.size);
++ return EINA_TRUE;
++}
++
+ void
+ nvim_mouse_enabled_set(s_nvim *nvim,
+ Eina_Bool enable)
+diff --git a/src/nvim_api.c b/src/nvim_api.c
+index 0b7e6ee..8082352 100644
+--- a/src/nvim_api.c
++++ b/src/nvim_api.c
+@@ -55,8 +55,13 @@ _request_new(s_nvim *nvim,
+ req->uid = nvim_next_uid_get(nvim);
+ DBG("Preparing request '%s' with id %"PRIu32, rpc_name, req->uid);
+
+- /* Clear the serialization buffer before pushing a new request */
+- msgpack_sbuffer_clear(&nvim->sbuffer);
++ /* The buffer MUST be empty before preparing another request. If this is not
++ * the case, something went very wrong! Discard the buffer and keep going */
++ if (EINA_UNLIKELY(nvim->sbuffer.size != 0u))
++ {
++ ERR("The buffer is not empty. I've messed up somewhere");
++ msgpack_sbuffer_clear(&nvim->sbuffer);
++ }
+
+ /* Keep the request around */
+ nvim->requests = eina_list_append(nvim->requests, req);
+@@ -91,19 +96,14 @@ _request_cleanup(s_nvim *nvim,
+ }
+
+ static Eina_Bool
+-_request_send(s_nvim *nvim,
+- s_request *req)
++_request_send(s_nvim *nvim, s_request *req)
+ {
+ /* Finally, send that to the slave neovim process */
+- const Eina_Bool ok =
+- ecore_exe_send(nvim->exe, nvim->sbuffer.data, (int)nvim->sbuffer.size);
+- if (EINA_UNLIKELY(! ok))
++ if (EINA_UNLIKELY(! nvim_flush(nvim)))
+ {
+- CRI("Failed to send %zu bytes to neovim", nvim->sbuffer.size);
+ _request_cleanup(nvim, req);
+ return EINA_FALSE;
+ }
+- DBG("Sent %zu bytes to neovim", nvim->sbuffer.size);
+ return EINA_TRUE;
+ }
+
+diff --git a/src/nvim_request.c b/src/nvim_request.c
+new file mode 100644
+index 0000000..7d34602
+--- /dev/null
++++ b/src/nvim_request.c
+@@ -0,0 +1,127 @@
++/*
++ * Copyright (c) 2019 Jean Guyomarc'h
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
++ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#include "eovim/nvim_request.h"
++#include "eovim/nvim.h"
++#include "eovim/log.h"
++
++static Eina_Hash *_nvim_requests;
++
++
++/*============================================================================*
++ * API *
++ *============================================================================*/
++
++Eina_Bool
++nvim_request_add(const char *request_name, f_nvim_request_cb func)
++{
++ Eina_Stringshare *const name = eina_stringshare_add(request_name);
++ const Eina_Bool ok = eina_hash_direct_add(_nvim_requests, name, func);
++ if (EINA_UNLIKELY(! ok))
++ {
++ ERR("Failed to register request \"%s\"", request_name);
++ return EINA_FALSE;
++ }
++ return EINA_TRUE;
++}
++
++void
++nvim_request_del(const char *request_name)
++{
++ Eina_Stringshare *const name = eina_stringshare_add(request_name);
++ eina_hash_del(_nvim_requests, name, NULL);
++ eina_stringshare_del(name);
++}
++
++Eina_Bool
++nvim_request_init(void)
++{
++ _nvim_requests = eina_hash_stringshared_new(NULL);
++ if (EINA_UNLIKELY(! _nvim_requests))
++ {
++ CRI("Failed to create hash table");
++ return EINA_FALSE;
++ }
++ return EINA_TRUE;
++}
++
++void
++nvim_request_shutdown(void)
++{
++ assert(_nvim_requests != NULL);
++ eina_hash_free(_nvim_requests);
++ _nvim_requests = NULL;
++}
++
++Eina_Bool
++nvim_request_process(s_nvim *nvim, Eina_Stringshare *request,
++ const msgpack_object_array *args, uint32_t req_id)
++{
++ /* This function shall only be used on the main loop. Otherwise, we cannot
++ * use this packer */
++ msgpack_packer *const pk = &nvim->packer;
++
++ /* The buffer MUST be empty before preparing the response. If this is not
++ * the case, something went very wrong! Discard the buffer and keep going */
++ if (EINA_UNLIKELY(nvim->sbuffer.size != 0u))
++ {
++ ERR("The buffer is not empty. I've messed up somewhere");
++ msgpack_sbuffer_clear(&nvim->sbuffer);
++ }
++
++ /*
++ * Pack the message! It is an array of four (4) items:
++ * - the rpc type:
++ * - 1 is a request response
++ * - the unique identifier of the request
++ * - the error return
++ * - the result return
++ *
++ * We start to reply with the two first elements. If we are not prepared to
++ * handle this request, we will finish the message with an error and no
++ * result. But if someone handles the request, it is up to the handler to
++ * finish the message by setting both the error and result.
++ */
++ msgpack_pack_array(pk, 4);
++ msgpack_pack_int(pk, 1);
++ msgpack_pack_uint32(pk, req_id);
++
++ const f_nvim_request_cb func = eina_hash_find(_nvim_requests, request);
++ if (EINA_UNLIKELY(! func))
++ {
++ WRN("No handler for request '%s'", request);
++ const char error[] = "unknown request";
++
++ /* See msgpack-rpc request response. Reply there is an error */
++ msgpack_pack_str(pk, sizeof(error) - 1u);
++ msgpack_pack_str_body(pk, error, sizeof(error) - 1u);
++ msgpack_pack_nil(pk);
++ nvim_flush(nvim);
++ return EINA_FALSE;
++ }
++ else
++ {
++ const Eina_Bool ok = func(nvim, args, pk);
++ nvim_flush(nvim);
++ return ok;
++ }
++}