diff --git a/src/main.cc b/src/main.cc index 09902b5d..618bd249 100644 --- a/src/main.cc +++ b/src/main.cc @@ -33,11 +33,12 @@ #include #include -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 make_ui(UIType ui_type) @@ -346,7 +336,7 @@ std::unique_ptr 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 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 create_local_ui(UIType ui_type) { if (ui_type != UIType::NCurses) @@ -436,37 +439,6 @@ std::unique_ptr create_local_ui(UIType ui_type) return make_unique(); } -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 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 : std::true_type {}; + int run_server(StringView session, StringView init_cmds, Optional init_coord, - bool ignore_kakrc, bool daemon, bool readonly, UIType ui_type, + ServerFlags flags, UIType ui_type, ConstArrayView 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(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 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"