Reorganize code in main.cc
This commit is contained in:
parent
d470bd2cc9
commit
9e0f085b86
171
src/main.cc
171
src/main.cc
|
@ -33,11 +33,12 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
|
|
||||||
using namespace Kakoune;
|
namespace Kakoune
|
||||||
|
|
||||||
struct startup_error : Kakoune::runtime_error
|
|
||||||
{
|
{
|
||||||
using Kakoune::runtime_error::runtime_error;
|
|
||||||
|
struct startup_error : runtime_error
|
||||||
|
{
|
||||||
|
using runtime_error::runtime_error;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void write_stdout(StringView str) { write(1, str); }
|
inline void write_stdout(StringView str) { write(1, str); }
|
||||||
|
@ -298,12 +299,9 @@ void register_options()
|
||||||
""_str);
|
""_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct convert_to_client_mode
|
static Client* local_client = nullptr;
|
||||||
{
|
static UserInterface* local_ui = nullptr;
|
||||||
String session;
|
static bool convert_to_client_pending = false;
|
||||||
String buffer_name;
|
|
||||||
String selections;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class UIType
|
enum class UIType
|
||||||
{
|
{
|
||||||
|
@ -312,21 +310,13 @@ enum class UIType
|
||||||
Dummy,
|
Dummy,
|
||||||
};
|
};
|
||||||
|
|
||||||
static Client* local_client = nullptr;
|
UIType parse_ui_type(StringView ui_name)
|
||||||
static UserInterface* local_ui = nullptr;
|
|
||||||
static bool convert_to_client_pending = false;
|
|
||||||
|
|
||||||
pid_t fork_server_to_background()
|
|
||||||
{
|
{
|
||||||
if (pid_t pid = fork())
|
if (ui_name == "ncurses") return UIType::NCurses;
|
||||||
return pid;
|
if (ui_name == "json") return UIType::Json;
|
||||||
|
if (ui_name == "dummy") return UIType::Dummy;
|
||||||
|
|
||||||
if (fork()) // double fork to orphan the server
|
throw parameter_error(format("error: unknown ui type: '{}'", ui_name));
|
||||||
exit(0);
|
|
||||||
|
|
||||||
write_stderr(format("Kakoune forked server to background ({}), for session '{}'\n",
|
|
||||||
getpid(), Server::instance().session()));
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<UserInterface> make_ui(UIType ui_type)
|
std::unique_ptr<UserInterface> make_ui(UIType ui_type)
|
||||||
|
@ -346,7 +336,7 @@ std::unique_ptr<UserInterface> make_ui(UIType ui_type)
|
||||||
void draw_status(const DisplayLine&, const DisplayLine&, const Face&) override {}
|
void draw_status(const DisplayLine&, const DisplayLine&, const Face&) override {}
|
||||||
DisplayCoord dimensions() override { return {24,80}; }
|
DisplayCoord dimensions() override { return {24,80}; }
|
||||||
void refresh(bool) override {}
|
void refresh(bool) override {}
|
||||||
void set_on_key(OnKeyCallback callback) override {}
|
void set_on_key(OnKeyCallback) override {}
|
||||||
void set_ui_options(const Options&) override {}
|
void set_ui_options(const Options&) override {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -359,6 +349,19 @@ std::unique_ptr<UserInterface> make_ui(UIType ui_type)
|
||||||
throw logic_error{};
|
throw logic_error{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pid_t fork_server_to_background()
|
||||||
|
{
|
||||||
|
if (pid_t pid = fork())
|
||||||
|
return pid;
|
||||||
|
|
||||||
|
if (fork()) // double fork to orphan the server
|
||||||
|
exit(0);
|
||||||
|
|
||||||
|
write_stderr(format("Kakoune forked server to background ({}), for session '{}'\n",
|
||||||
|
getpid(), Server::instance().session()));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<UserInterface> create_local_ui(UIType ui_type)
|
std::unique_ptr<UserInterface> create_local_ui(UIType ui_type)
|
||||||
{
|
{
|
||||||
if (ui_type != UIType::NCurses)
|
if (ui_type != UIType::NCurses)
|
||||||
|
@ -436,37 +439,6 @@ std::unique_ptr<UserInterface> create_local_ui(UIType ui_type)
|
||||||
return make_unique<LocalUI>();
|
return make_unique<LocalUI>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void signal_handler(int signal)
|
|
||||||
{
|
|
||||||
NCursesUI::abort();
|
|
||||||
const char* text = nullptr;
|
|
||||||
switch (signal)
|
|
||||||
{
|
|
||||||
case SIGSEGV: text = "SIGSEGV"; break;
|
|
||||||
case SIGFPE: text = "SIGFPE"; break;
|
|
||||||
case SIGQUIT: text = "SIGQUIT"; break;
|
|
||||||
case SIGTERM: text = "SIGTERM"; break;
|
|
||||||
case SIGPIPE: text = "SIGPIPE"; break;
|
|
||||||
}
|
|
||||||
if (signal != SIGTERM)
|
|
||||||
{
|
|
||||||
auto msg = format("Received {}, exiting.\nPid: {}\nCallstack:\n{}",
|
|
||||||
text, getpid(), Backtrace{}.desc());
|
|
||||||
write_stderr(msg);
|
|
||||||
notify_fatal_error(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Server::has_instance())
|
|
||||||
Server::instance().close_session();
|
|
||||||
if (BufferManager::has_instance())
|
|
||||||
BufferManager::instance().backup_modified_buffers();
|
|
||||||
|
|
||||||
if (signal == SIGTERM)
|
|
||||||
exit(-1);
|
|
||||||
else
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
int run_client(StringView session, StringView init_cmds,
|
int run_client(StringView session, StringView init_cmds,
|
||||||
Optional<BufferCoord> init_coord, UIType ui_type)
|
Optional<BufferCoord> init_coord, UIType ui_type)
|
||||||
{
|
{
|
||||||
|
@ -486,13 +458,29 @@ int run_client(StringView session, StringView init_cmds,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct convert_to_client_mode
|
||||||
|
{
|
||||||
|
String session;
|
||||||
|
String buffer_name;
|
||||||
|
String selections;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class ServerFlags
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
IgnoreKakrc = 1 << 0,
|
||||||
|
Daemon = 1 << 1,
|
||||||
|
ReadOnly = 1 << 2,
|
||||||
|
};
|
||||||
|
template<> struct WithBitOps<ServerFlags> : std::true_type {};
|
||||||
|
|
||||||
int run_server(StringView session,
|
int run_server(StringView session,
|
||||||
StringView init_cmds, Optional<BufferCoord> init_coord,
|
StringView init_cmds, Optional<BufferCoord> init_coord,
|
||||||
bool ignore_kakrc, bool daemon, bool readonly, UIType ui_type,
|
ServerFlags flags, UIType ui_type,
|
||||||
ConstArrayView<StringView> files)
|
ConstArrayView<StringView> files)
|
||||||
{
|
{
|
||||||
static bool terminate = false;
|
static bool terminate = false;
|
||||||
if (daemon)
|
if (flags & ServerFlags::Daemon)
|
||||||
{
|
{
|
||||||
if (session.empty())
|
if (session.empty())
|
||||||
{
|
{
|
||||||
|
@ -531,18 +519,18 @@ int run_server(StringView session,
|
||||||
|
|
||||||
write_to_debug_buffer("*** This is the debug buffer, where debug info will be written ***");
|
write_to_debug_buffer("*** This is the debug buffer, where debug info will be written ***");
|
||||||
|
|
||||||
GlobalScope::instance().options().get_local_option("readonly").set(readonly);
|
GlobalScope::instance().options().get_local_option("readonly").set<bool>(flags & ServerFlags::ReadOnly);
|
||||||
|
|
||||||
Server server{session.empty() ? to_string(getpid()) : session.str()};
|
Server server{session.empty() ? to_string(getpid()) : session.str()};
|
||||||
|
|
||||||
bool startup_error = false;
|
bool startup_error = false;
|
||||||
if (not ignore_kakrc) try
|
if (not (flags & ServerFlags::IgnoreKakrc)) try
|
||||||
{
|
{
|
||||||
Context initialisation_context{Context::EmptyContextFlag{}};
|
Context initialisation_context{Context::EmptyContextFlag{}};
|
||||||
command_manager.execute(format("source {}/kakrc", runtime_directory()),
|
command_manager.execute(format("source {}/kakrc", runtime_directory()),
|
||||||
initialisation_context);
|
initialisation_context);
|
||||||
}
|
}
|
||||||
catch (Kakoune::runtime_error& error)
|
catch (runtime_error& error)
|
||||||
{
|
{
|
||||||
startup_error = true;
|
startup_error = true;
|
||||||
write_to_debug_buffer(format("error while parsing kakrc:\n"
|
write_to_debug_buffer(format("error while parsing kakrc:\n"
|
||||||
|
@ -563,10 +551,10 @@ int run_server(StringView session,
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Buffer *buffer = open_or_create_file_buffer(file);
|
Buffer *buffer = open_or_create_file_buffer(file);
|
||||||
if (readonly)
|
if (flags & ServerFlags::ReadOnly)
|
||||||
buffer->flags() |= Buffer::Flags::ReadOnly;
|
buffer->flags() |= Buffer::Flags::ReadOnly;
|
||||||
}
|
}
|
||||||
catch (Kakoune::runtime_error& error)
|
catch (runtime_error& error)
|
||||||
{
|
{
|
||||||
startup_error = true;
|
startup_error = true;
|
||||||
write_to_debug_buffer(format("error while opening file '{}':\n"
|
write_to_debug_buffer(format("error while opening file '{}':\n"
|
||||||
|
@ -574,14 +562,14 @@ int run_server(StringView session,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Kakoune::runtime_error& error)
|
catch (runtime_error& error)
|
||||||
{
|
{
|
||||||
write_to_debug_buffer(format("error while opening command line files: {}", error.what()));
|
write_to_debug_buffer(format("error while opening command line files: {}", error.what()));
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (not daemon)
|
if (not (flags & ServerFlags::Daemon))
|
||||||
local_client = client_manager.create_client(
|
local_client = client_manager.create_client(
|
||||||
create_local_ui(ui_type), get_env_vars(), init_cmds, init_coord);
|
create_local_ui(ui_type), get_env_vars(), init_cmds, init_coord);
|
||||||
|
|
||||||
|
@ -591,7 +579,7 @@ int run_server(StringView session,
|
||||||
get_face("Error")
|
get_face("Error")
|
||||||
});
|
});
|
||||||
|
|
||||||
while (not terminate and (not client_manager.empty() or daemon))
|
while (not terminate and (not client_manager.empty() or (flags & ServerFlags::Daemon)))
|
||||||
{
|
{
|
||||||
client_manager.redraw_clients();
|
client_manager.redraw_clients();
|
||||||
event_manager.handle_next_events(EventMode::Normal);
|
event_manager.handle_next_events(EventMode::Normal);
|
||||||
|
@ -665,7 +653,7 @@ int run_filter(StringView keystr, StringView commands, ConstArrayView<StringView
|
||||||
for (auto& key : keys)
|
for (auto& key : keys)
|
||||||
input_handler.handle_key(key);
|
input_handler.handle_key(key);
|
||||||
}
|
}
|
||||||
catch (Kakoune::runtime_error& err)
|
catch (runtime_error& err)
|
||||||
{
|
{
|
||||||
if (not quiet)
|
if (not quiet)
|
||||||
write_stderr(format("error while applying keys to buffer '{}': {}\n",
|
write_stderr(format("error while applying keys to buffer '{}': {}\n",
|
||||||
|
@ -690,7 +678,7 @@ int run_filter(StringView keystr, StringView commands, ConstArrayView<StringView
|
||||||
buffer_manager.delete_buffer(buffer);
|
buffer_manager.delete_buffer(buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Kakoune::runtime_error& err)
|
catch (runtime_error& err)
|
||||||
{
|
{
|
||||||
write_stderr(format("error: {}\n", err.what()));
|
write_stderr(format("error: {}\n", err.what()));
|
||||||
}
|
}
|
||||||
|
@ -724,17 +712,43 @@ int run_pipe(StringView session)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
UIType parse_ui_type(StringView ui_name)
|
void signal_handler(int signal)
|
||||||
{
|
{
|
||||||
if (ui_name == "ncurses") return UIType::NCurses;
|
NCursesUI::abort();
|
||||||
if (ui_name == "json") return UIType::Json;
|
const char* text = nullptr;
|
||||||
if (ui_name == "dummy") return UIType::Dummy;
|
switch (signal)
|
||||||
|
{
|
||||||
|
case SIGSEGV: text = "SIGSEGV"; break;
|
||||||
|
case SIGFPE: text = "SIGFPE"; break;
|
||||||
|
case SIGQUIT: text = "SIGQUIT"; break;
|
||||||
|
case SIGTERM: text = "SIGTERM"; break;
|
||||||
|
case SIGPIPE: text = "SIGPIPE"; break;
|
||||||
|
}
|
||||||
|
if (signal != SIGTERM)
|
||||||
|
{
|
||||||
|
auto msg = format("Received {}, exiting.\nPid: {}\nCallstack:\n{}",
|
||||||
|
text, getpid(), Backtrace{}.desc());
|
||||||
|
write_stderr(msg);
|
||||||
|
notify_fatal_error(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Server::has_instance())
|
||||||
|
Server::instance().close_session();
|
||||||
|
if (BufferManager::has_instance())
|
||||||
|
BufferManager::instance().backup_modified_buffers();
|
||||||
|
|
||||||
|
if (signal == SIGTERM)
|
||||||
|
exit(-1);
|
||||||
|
else
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
throw parameter_error(format("error: unknown ui type: '{}'", ui_name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
using namespace Kakoune;
|
||||||
|
|
||||||
setlocale(LC_ALL, "");
|
setlocale(LC_ALL, "");
|
||||||
|
|
||||||
set_signal_handler(SIGSEGV, signal_handler);
|
set_signal_handler(SIGSEGV, signal_handler);
|
||||||
|
@ -746,7 +760,7 @@ int main(int argc, char* argv[])
|
||||||
set_signal_handler(SIGCHLD, [](int){});
|
set_signal_handler(SIGCHLD, [](int){});
|
||||||
|
|
||||||
Vector<String> params;
|
Vector<String> params;
|
||||||
for (size_t i = 1; i < argc; ++i)
|
for (int i = 1; i < argc; ++i)
|
||||||
params.emplace_back(argv[i]);
|
params.emplace_back(argv[i]);
|
||||||
|
|
||||||
const ParameterDesc param_desc{
|
const ParameterDesc param_desc{
|
||||||
|
@ -875,11 +889,10 @@ int main(int argc, char* argv[])
|
||||||
StringView session = parser.get_switch("s").value_or(StringView{});
|
StringView session = parser.get_switch("s").value_or(StringView{});
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return run_server(session, init_cmds, init_coord,
|
auto flags = (parser.get_switch("n") ? ServerFlags::IgnoreKakrc : ServerFlags::None) |
|
||||||
(bool)parser.get_switch("n"),
|
(parser.get_switch("d") ? ServerFlags::Daemon : ServerFlags::None) |
|
||||||
(bool)parser.get_switch("d"),
|
(parser.get_switch("ro") ? ServerFlags::ReadOnly : ServerFlags::None);
|
||||||
(bool)parser.get_switch("ro"),
|
return run_server(session, init_cmds, init_coord, flags, ui_type, files);
|
||||||
ui_type, files);
|
|
||||||
}
|
}
|
||||||
catch (convert_to_client_mode& convert)
|
catch (convert_to_client_mode& convert)
|
||||||
{
|
{
|
||||||
|
@ -890,7 +903,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Kakoune::parameter_error& error)
|
catch (parameter_error& error)
|
||||||
{
|
{
|
||||||
write_stderr(format("Error while parsing parameters: {}\n"
|
write_stderr(format("Error while parsing parameters: {}\n"
|
||||||
"Valid switches:\n"
|
"Valid switches:\n"
|
||||||
|
|
Loading…
Reference in New Issue
Block a user