From e8ee8c23d837d64b1df1d39a97acb88c7cb207de Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sat, 21 Jan 2017 12:14:44 +0000 Subject: [PATCH] Support the +line syntax for clients as well. Fix a crash on daemon quit as well. --- src/client_manager.cc | 2 ++ src/main.cc | 54 +++++++++++++++++++++++-------------------- src/remote.cc | 24 +++++++++++++++++-- src/remote.hh | 6 ++++- 4 files changed, 58 insertions(+), 28 deletions(-) diff --git a/src/client_manager.cc b/src/client_manager.cc index c7246a822..0053ebf0e 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -22,8 +22,10 @@ void ClientManager::clear() // So that clients destructor find the client manager empty // so that local UI does not fork. ClientList clients = std::move(m_clients); + clients.clear(); m_client_trash.clear(); m_free_windows.clear(); + m_window_trash.clear(); } String ClientManager::generate_name() const diff --git a/src/main.cc b/src/main.cc index a0fa3f090..a41ebad1b 100644 --- a/src/main.cc +++ b/src/main.cc @@ -454,12 +454,13 @@ void signal_handler(int signal) abort(); } -int run_client(StringView session, StringView init_cmds, UIType ui_type) +int run_client(StringView session, StringView init_cmds, + Optional init_coord, UIType ui_type) { try { EventManager event_manager; - RemoteClient client{session, make_ui(ui_type), get_env_vars(), init_cmds}; + RemoteClient client{session, make_ui(ui_type), get_env_vars(), init_cmds, init_coord}; while (true) event_manager.handle_next_events(EventMode::Normal); } @@ -473,7 +474,7 @@ int run_client(StringView session, StringView init_cmds, UIType ui_type) } int run_server(StringView session, - StringView init_cmds, BufferCoord init_coord, + StringView init_cmds, Optional init_coord, bool ignore_kakrc, bool daemon, bool readonly, UIType ui_type, ConstArrayView files) { @@ -812,6 +813,28 @@ int main(int argc, char* argv[]) (bool)parser.get_switch("q")); } + Vector files; + Optional init_coord; + for (auto& name : parser) + { + if (not name.empty() and name[0_byte] == '+') + { + auto colon = find(name, ':'); + if (auto line = str_to_int_ifp({name.begin()+1, colon})) + { + init_coord = BufferCoord{ + *line - 1, + colon != name.end() ? + str_to_int_ifp({colon+1, name.end()}).value_or(1) - 1 + : 0 + }; + continue; + } + } + + files.emplace_back(name); + } + if (auto server_session = parser.get_switch("c")) { for (auto opt : { "n", "s", "d", "ro" }) @@ -823,32 +846,13 @@ int main(int argc, char* argv[]) } } String new_files; - for (auto name : parser) + for (auto name : files) new_files += format("edit '{}';", escape(real_path(name), "'", '\\')); - return run_client(*server_session, new_files + init_cmds, ui_type); + return run_client(*server_session, new_files + init_cmds, init_coord, ui_type); } else { - BufferCoord init_coord; - Vector files; - for (auto& name : parser) - { - if (not name.empty() and name[0_byte] == '+') - { - auto colon = find(name, ':'); - if (auto line = str_to_int_ifp({name.begin()+1, colon})) - { - init_coord.line = *line - 1; - if (colon != name.end()) - init_coord.column = str_to_int_ifp({colon+1, name.end()}).value_or(1) - 1; - - continue; - } - } - - files.emplace_back(name); - } StringView session = parser.get_switch("s").value_or(StringView{}); try @@ -864,7 +868,7 @@ int main(int argc, char* argv[]) raise(SIGTSTP); return run_client(convert.session, format("try %^buffer '{}'; select '{}'^; echo converted to client only mode", - escape(convert.buffer_name, "'^", '\\'), convert.selections), ui_type); + escape(convert.buffer_name, "'^", '\\'), convert.selections), {}, ui_type); } } } diff --git a/src/remote.cc b/src/remote.cc index 016ba23c6..6a436d5c8 100644 --- a/src/remote.cc +++ b/src/remote.cc @@ -8,6 +8,7 @@ #include "event_manager.hh" #include "file.hh" #include "id_map.hh" +#include "optional.hh" #include "user_interface.hh" #include @@ -102,6 +103,14 @@ public: } } + template + void write(const Optional& val) + { + write((bool)val); + if (val) + write(*val); + } + void write(Color color) { write(color.color); @@ -219,6 +228,14 @@ public: return res; } + template + Optional read_optional() + { + if (not read()) + return {}; + return read(); + } + void reset() { m_stream.resize(0); @@ -511,7 +528,8 @@ bool check_session(StringView session) } RemoteClient::RemoteClient(StringView session, std::unique_ptr&& ui, - const EnvVarMap& env_vars, StringView init_command) + const EnvVarMap& env_vars, StringView init_command, + Optional init_coord) : m_ui(std::move(ui)) { int sock = connect_to(session); @@ -519,6 +537,7 @@ RemoteClient::RemoteClient(StringView session, std::unique_ptr&& { MsgWriter msg{m_send_buffer, MessageType::Connect}; msg.write(init_command); + msg.write(init_coord); msg.write(m_ui->dimensions()); msg.write(env_vars); } @@ -652,12 +671,13 @@ private: case MessageType::Connect: { auto init_cmds = m_reader.read(); + auto init_coord = m_reader.read_optional(); auto dimensions = m_reader.read(); auto env_vars = m_reader.read_idmap(); auto* ui = new RemoteUI{sock, dimensions}; if (auto* client = ClientManager::instance().create_client( std::unique_ptr(ui), - std::move(env_vars), init_cmds, {})) + std::move(env_vars), init_cmds, init_coord)) ui->set_client(client); Server::instance().remove_accepter(this); diff --git a/src/remote.hh b/src/remote.hh index 111a49735..b0cad37c7 100644 --- a/src/remote.hh +++ b/src/remote.hh @@ -22,6 +22,9 @@ struct disconnected : runtime_error class FDWatcher; class UserInterface; +template struct Optional; +struct BufferCoord; + using RemoteBuffer = Vector; // A remote client handle communication between a client running on the server @@ -30,7 +33,8 @@ class RemoteClient { public: RemoteClient(StringView session, std::unique_ptr&& ui, - const EnvVarMap& env_vars, StringView init_command); + const EnvVarMap& env_vars, StringView init_command, + Optional init_coord); private: std::unique_ptr m_ui;