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 <pwd.h>
|
||||
|
||||
using namespace Kakoune;
|
||||
|
||||
struct startup_error : Kakoune::runtime_error
|
||||
namespace Kakoune
|
||||
{
|
||||
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); }
|
||||
|
@ -298,12 +299,9 @@ void register_options()
|
|||
""_str);
|
||||
}
|
||||
|
||||
struct convert_to_client_mode
|
||||
{
|
||||
String session;
|
||||
String buffer_name;
|
||||
String selections;
|
||||
};
|
||||
static Client* local_client = nullptr;
|
||||
static UserInterface* local_ui = nullptr;
|
||||
static bool convert_to_client_pending = false;
|
||||
|
||||
enum class UIType
|
||||
{
|
||||
|
@ -312,21 +310,13 @@ enum class UIType
|
|||
Dummy,
|
||||
};
|
||||
|
||||
static Client* local_client = nullptr;
|
||||
static UserInterface* local_ui = nullptr;
|
||||
static bool convert_to_client_pending = false;
|
||||
|
||||
pid_t fork_server_to_background()
|
||||
UIType parse_ui_type(StringView ui_name)
|
||||
{
|
||||
if (pid_t pid = fork())
|
||||
return pid;
|
||||
if (ui_name == "ncurses") return UIType::NCurses;
|
||||
if (ui_name == "json") return UIType::Json;
|
||||
if (ui_name == "dummy") return UIType::Dummy;
|
||||
|
||||
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;
|
||||
throw parameter_error(format("error: unknown ui type: '{}'", ui_name));
|
||||
}
|
||||
|
||||
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 {}
|
||||
DisplayCoord dimensions() override { return {24,80}; }
|
||||
void refresh(bool) override {}
|
||||
void set_on_key(OnKeyCallback callback) override {}
|
||||
void set_on_key(OnKeyCallback) override {}
|
||||
void set_ui_options(const Options&) override {}
|
||||
};
|
||||
|
||||
|
@ -359,6 +349,19 @@ std::unique_ptr<UserInterface> make_ui(UIType ui_type)
|
|||
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)
|
||||
{
|
||||
if (ui_type != UIType::NCurses)
|
||||
|
@ -436,37 +439,6 @@ std::unique_ptr<UserInterface> create_local_ui(UIType ui_type)
|
|||
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,
|
||||
Optional<BufferCoord> init_coord, UIType ui_type)
|
||||
{
|
||||
|
@ -486,13 +458,29 @@ int run_client(StringView session, StringView init_cmds,
|
|||
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,
|
||||
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)
|
||||
{
|
||||
static bool terminate = false;
|
||||
if (daemon)
|
||||
if (flags & ServerFlags::Daemon)
|
||||
{
|
||||
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 ***");
|
||||
|
||||
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()};
|
||||
|
||||
bool startup_error = false;
|
||||
if (not ignore_kakrc) try
|
||||
if (not (flags & ServerFlags::IgnoreKakrc)) try
|
||||
{
|
||||
Context initialisation_context{Context::EmptyContextFlag{}};
|
||||
command_manager.execute(format("source {}/kakrc", runtime_directory()),
|
||||
initialisation_context);
|
||||
}
|
||||
catch (Kakoune::runtime_error& error)
|
||||
catch (runtime_error& error)
|
||||
{
|
||||
startup_error = true;
|
||||
write_to_debug_buffer(format("error while parsing kakrc:\n"
|
||||
|
@ -563,10 +551,10 @@ int run_server(StringView session,
|
|||
try
|
||||
{
|
||||
Buffer *buffer = open_or_create_file_buffer(file);
|
||||
if (readonly)
|
||||
if (flags & ServerFlags::ReadOnly)
|
||||
buffer->flags() |= Buffer::Flags::ReadOnly;
|
||||
}
|
||||
catch (Kakoune::runtime_error& error)
|
||||
catch (runtime_error& error)
|
||||
{
|
||||
startup_error = true;
|
||||
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()));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (not daemon)
|
||||
if (not (flags & ServerFlags::Daemon))
|
||||
local_client = client_manager.create_client(
|
||||
create_local_ui(ui_type), get_env_vars(), init_cmds, init_coord);
|
||||
|
||||
|
@ -591,7 +579,7 @@ int run_server(StringView session,
|
|||
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();
|
||||
event_manager.handle_next_events(EventMode::Normal);
|
||||
|
@ -665,7 +653,7 @@ int run_filter(StringView keystr, StringView commands, ConstArrayView<StringView
|
|||
for (auto& key : keys)
|
||||
input_handler.handle_key(key);
|
||||
}
|
||||
catch (Kakoune::runtime_error& err)
|
||||
catch (runtime_error& err)
|
||||
{
|
||||
if (not quiet)
|
||||
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);
|
||||
}
|
||||
}
|
||||
catch (Kakoune::runtime_error& err)
|
||||
catch (runtime_error& err)
|
||||
{
|
||||
write_stderr(format("error: {}\n", err.what()));
|
||||
}
|
||||
|
@ -724,17 +712,43 @@ int run_pipe(StringView session)
|
|||
return 0;
|
||||
}
|
||||
|
||||
UIType parse_ui_type(StringView ui_name)
|
||||
void signal_handler(int signal)
|
||||
{
|
||||
if (ui_name == "ncurses") return UIType::NCurses;
|
||||
if (ui_name == "json") return UIType::Json;
|
||||
if (ui_name == "dummy") return UIType::Dummy;
|
||||
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();
|
||||
}
|
||||
|
||||
throw parameter_error(format("error: unknown ui type: '{}'", ui_name));
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
using namespace Kakoune;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
set_signal_handler(SIGSEGV, signal_handler);
|
||||
|
@ -746,7 +760,7 @@ int main(int argc, char* argv[])
|
|||
set_signal_handler(SIGCHLD, [](int){});
|
||||
|
||||
Vector<String> params;
|
||||
for (size_t i = 1; i < argc; ++i)
|
||||
for (int i = 1; i < argc; ++i)
|
||||
params.emplace_back(argv[i]);
|
||||
|
||||
const ParameterDesc param_desc{
|
||||
|
@ -875,11 +889,10 @@ int main(int argc, char* argv[])
|
|||
StringView session = parser.get_switch("s").value_or(StringView{});
|
||||
try
|
||||
{
|
||||
return run_server(session, init_cmds, init_coord,
|
||||
(bool)parser.get_switch("n"),
|
||||
(bool)parser.get_switch("d"),
|
||||
(bool)parser.get_switch("ro"),
|
||||
ui_type, files);
|
||||
auto flags = (parser.get_switch("n") ? ServerFlags::IgnoreKakrc : ServerFlags::None) |
|
||||
(parser.get_switch("d") ? ServerFlags::Daemon : ServerFlags::None) |
|
||||
(parser.get_switch("ro") ? ServerFlags::ReadOnly : ServerFlags::None);
|
||||
return run_server(session, init_cmds, init_coord, flags, ui_type, files);
|
||||
}
|
||||
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"
|
||||
"Valid switches:\n"
|
||||
|
|
Loading…
Reference in New Issue
Block a user