diff --git a/vim_research/test1.cpp b/vim_research/test1.cpp index 4e494cc..ab296d0 100644 --- a/vim_research/test1.cpp +++ b/vim_research/test1.cpp @@ -1,6 +1,8 @@ #include +#include #include +#include #include #include @@ -11,6 +13,32 @@ using Agent = char; using DocType = GreenCRDT::TextDocument; using ListType = DocType::ListType; +static bool send_command(zed_net_socket_t* remote_socket, const std::string_view mode, const std::string_view command) { + auto j = nlohmann::json::array(); + + j.push_back(mode); + j.push_back(command); + + std::string str = j.dump(); + str += '\n'; + auto ret = zed_net_tcp_socket_send(remote_socket, str.data(), str.size()); + + return ret == 0; +} + +static bool send_setup(zed_net_socket_t* remote_socket) { + //send_command(remote_socket, "ex", "let b:green_crdt_timer_can_send = v:true"); + //send_command(remote_socket, "ex", ""); + send_command(remote_socket, "ex", "augroup green_crdt"); + send_command(remote_socket, "ex", "au!"); // delete the group, prevent double trigger + send_command(remote_socket, "ex", "au TextChanged call ch_sendexpr(channel, [{'cmd': 'full_buffer', 'lines': getbufline(bufnr(), 1, '$')}])"); + send_command(remote_socket, "ex", "au TextChangedI call ch_sendexpr(channel, [{'cmd': 'full_buffer', 'lines': getbufline(bufnr(), 1, '$')}])"); + send_command(remote_socket, "ex", "augroup END"); + send_command(remote_socket, "ex", "echo 'setup done'"); + + return true; +} + int main(void) { std::cout << "starting vim ipc server\n"; @@ -36,6 +64,12 @@ int main(void) { std::cout << "listening on " << port << "\n"; + std::cout << "paste these commands into your vim for the current buffer:\n"; + std::cout << " :let channel = ch_open('localhost:" << port << "')\n"; + //std::cout << " :call ch_sendexpr(channel, [{'cmd': 'setup'}])\n"; + + std::cout << "paste this command to disconnect:\n :call ch_close(channel)\n"; + zed_net_socket_t remote_socket; zed_net_address_t remote_address; if (zed_net_tcp_accept(&listen_socket, &remote_socket, &remote_address) != 0) { @@ -47,6 +81,10 @@ int main(void) { std::cout << "got connection from " << zed_net_host_to_str(remote_address.host) << ":" << remote_address.port << "\n"; + std::cout << "sending setup\n"; + send_setup(&remote_socket); + // send doauto text changed for inital buffer + while (true) { // 10MiB auto buffer = std::make_unique>(); @@ -65,11 +103,87 @@ int main(void) { } std::cout << "got " << bytes_received << " bytes\n"; - // do data decoding + + // expect json array(s separated by newlines) + // TODO: new lines + auto view = std::string_view{reinterpret_cast(buffer->data()), static_cast(bytes_received)}; + std::cout << " raw: " << view; + + auto j = nlohmann::json::parse(view, nullptr, false); + if (j.is_discarded()) { + std::cerr << "invalid json\n"; + break; + } + + //std::cout << " j: " << j.dump() << "\n"; + + if (!j.is_array()) { + std::cerr << "json not array!\n"; + break; + } + + int64_t command_seq = j.at(0); + auto j_command_data = j.at(1); + + if (!j_command_data.is_array()) { + std::cerr << "j_command_data not array!\n"; + break; + } + + for (const auto& j_command : j_command_data) { + if (!j_command.is_object()) { + std::cerr << "j_command not obj!\n"; + break; + } + + if (!j_command.count("cmd")) { + std::cerr << "j_command does not have a 'cmd' field!\n"; + break; + } + + if (!j_command.at("cmd").is_string()) { + std::cerr << "command not a string!\n"; + break; + } + + std::string command = j_command.at("cmd"); + + if (command.empty()) { + std::cerr << "command string empty!\n"; + break; + } else if (command == "setup") { // setup callbacks etc, basically the plugin + std::cout << "sending setup\n"; + send_setup(&remote_socket); + } else if (command == "full_buffer") { // vim is sending the full buffer + // array of lines + + if (!j_command.count("lines")) { + std::cerr << "lines list empty!\n"; + continue; + } + + const auto& j_lines = j_command.at("lines"); + if (!j_lines.is_array()) { + std::cerr << "lines list not an array!\n"; + continue; + } + + std::string new_text; + for (const auto& line : j_lines) { + new_text += line; + new_text += '\n'; + } + + //std::cout << "new_text: " << new_text << "\n"; + } else { + std::cout << "unknown command '" << command << "'\n"; + } + } } std::cout << "shutting down\n"; + zed_net_socket_close(&remote_socket); zed_net_socket_close(&listen_socket); zed_net_shutdown(); return 0;