Support the +line syntax for clients as well.

Fix a crash on daemon quit as well.
This commit is contained in:
Maxime Coste 2017-01-21 12:14:44 +00:00
parent c6a7924b80
commit e8ee8c23d8
4 changed files with 58 additions and 28 deletions

View File

@ -22,8 +22,10 @@ void ClientManager::clear()
// So that clients destructor find the client manager empty // So that clients destructor find the client manager empty
// so that local UI does not fork. // so that local UI does not fork.
ClientList clients = std::move(m_clients); ClientList clients = std::move(m_clients);
clients.clear();
m_client_trash.clear(); m_client_trash.clear();
m_free_windows.clear(); m_free_windows.clear();
m_window_trash.clear();
} }
String ClientManager::generate_name() const String ClientManager::generate_name() const

View File

@ -454,12 +454,13 @@ void signal_handler(int signal)
abort(); abort();
} }
int run_client(StringView session, StringView init_cmds, UIType ui_type) int run_client(StringView session, StringView init_cmds,
Optional<BufferCoord> init_coord, UIType ui_type)
{ {
try try
{ {
EventManager event_manager; 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) while (true)
event_manager.handle_next_events(EventMode::Normal); 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, int run_server(StringView session,
StringView init_cmds, BufferCoord init_coord, StringView init_cmds, Optional<BufferCoord> init_coord,
bool ignore_kakrc, bool daemon, bool readonly, UIType ui_type, bool ignore_kakrc, bool daemon, bool readonly, UIType ui_type,
ConstArrayView<StringView> files) ConstArrayView<StringView> files)
{ {
@ -812,6 +813,28 @@ int main(int argc, char* argv[])
(bool)parser.get_switch("q")); (bool)parser.get_switch("q"));
} }
Vector<StringView> files;
Optional<BufferCoord> 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")) if (auto server_session = parser.get_switch("c"))
{ {
for (auto opt : { "n", "s", "d", "ro" }) for (auto opt : { "n", "s", "d", "ro" })
@ -823,32 +846,13 @@ int main(int argc, char* argv[])
} }
} }
String new_files; String new_files;
for (auto name : parser) for (auto name : files)
new_files += format("edit '{}';", escape(real_path(name), "'", '\\')); 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 else
{ {
BufferCoord init_coord;
Vector<StringView> 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{}); StringView session = parser.get_switch("s").value_or(StringView{});
try try
@ -864,7 +868,7 @@ int main(int argc, char* argv[])
raise(SIGTSTP); raise(SIGTSTP);
return run_client(convert.session, return run_client(convert.session,
format("try %^buffer '{}'; select '{}'^; echo converted to client only mode", 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);
} }
} }
} }

View File

@ -8,6 +8,7 @@
#include "event_manager.hh" #include "event_manager.hh"
#include "file.hh" #include "file.hh"
#include "id_map.hh" #include "id_map.hh"
#include "optional.hh"
#include "user_interface.hh" #include "user_interface.hh"
#include <sys/types.h> #include <sys/types.h>
@ -102,6 +103,14 @@ public:
} }
} }
template<typename T>
void write(const Optional<T>& val)
{
write((bool)val);
if (val)
write(*val);
}
void write(Color color) void write(Color color)
{ {
write(color.color); write(color.color);
@ -219,6 +228,14 @@ public:
return res; return res;
} }
template<typename T>
Optional<T> read_optional()
{
if (not read<bool>())
return {};
return read<T>();
}
void reset() void reset()
{ {
m_stream.resize(0); m_stream.resize(0);
@ -511,7 +528,8 @@ bool check_session(StringView session)
} }
RemoteClient::RemoteClient(StringView session, std::unique_ptr<UserInterface>&& ui, RemoteClient::RemoteClient(StringView session, std::unique_ptr<UserInterface>&& ui,
const EnvVarMap& env_vars, StringView init_command) const EnvVarMap& env_vars, StringView init_command,
Optional<BufferCoord> init_coord)
: m_ui(std::move(ui)) : m_ui(std::move(ui))
{ {
int sock = connect_to(session); int sock = connect_to(session);
@ -519,6 +537,7 @@ RemoteClient::RemoteClient(StringView session, std::unique_ptr<UserInterface>&&
{ {
MsgWriter msg{m_send_buffer, MessageType::Connect}; MsgWriter msg{m_send_buffer, MessageType::Connect};
msg.write(init_command); msg.write(init_command);
msg.write(init_coord);
msg.write(m_ui->dimensions()); msg.write(m_ui->dimensions());
msg.write(env_vars); msg.write(env_vars);
} }
@ -652,12 +671,13 @@ private:
case MessageType::Connect: case MessageType::Connect:
{ {
auto init_cmds = m_reader.read<String>(); auto init_cmds = m_reader.read<String>();
auto init_coord = m_reader.read_optional<BufferCoord>();
auto dimensions = m_reader.read<DisplayCoord>(); auto dimensions = m_reader.read<DisplayCoord>();
auto env_vars = m_reader.read_idmap<String, MemoryDomain::EnvVars>(); auto env_vars = m_reader.read_idmap<String, MemoryDomain::EnvVars>();
auto* ui = new RemoteUI{sock, dimensions}; auto* ui = new RemoteUI{sock, dimensions};
if (auto* client = ClientManager::instance().create_client( if (auto* client = ClientManager::instance().create_client(
std::unique_ptr<UserInterface>(ui), std::unique_ptr<UserInterface>(ui),
std::move(env_vars), init_cmds, {})) std::move(env_vars), init_cmds, init_coord))
ui->set_client(client); ui->set_client(client);
Server::instance().remove_accepter(this); Server::instance().remove_accepter(this);

View File

@ -22,6 +22,9 @@ struct disconnected : runtime_error
class FDWatcher; class FDWatcher;
class UserInterface; class UserInterface;
template<typename T> struct Optional;
struct BufferCoord;
using RemoteBuffer = Vector<char, MemoryDomain::Remote>; using RemoteBuffer = Vector<char, MemoryDomain::Remote>;
// A remote client handle communication between a client running on the server // A remote client handle communication between a client running on the server
@ -30,7 +33,8 @@ class RemoteClient
{ {
public: public:
RemoteClient(StringView session, std::unique_ptr<UserInterface>&& ui, RemoteClient(StringView session, std::unique_ptr<UserInterface>&& ui,
const EnvVarMap& env_vars, StringView init_command); const EnvVarMap& env_vars, StringView init_command,
Optional<BufferCoord> init_coord);
private: private:
std::unique_ptr<UserInterface> m_ui; std::unique_ptr<UserInterface> m_ui;