From b2407d9dfa1ec1b4a22fba7458d3e185f262edb6 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 10 Nov 2014 23:29:16 +0000 Subject: [PATCH] Add ui_options option for UserInterface configuration ui_options is a std::unordered_map that gets forwarded to the user interface. Add support ncurses_status_on_top. --- src/client.cc | 16 ++++++++++++++++ src/client.hh | 7 ++++++- src/main.cc | 3 +++ src/ncurses.cc | 23 ++++++++++++++--------- src/ncurses.hh | 4 ++++ src/remote.cc | 15 ++++++++++++++- src/user_interface.hh | 5 +++++ 7 files changed, 62 insertions(+), 11 deletions(-) diff --git a/src/client.cc b/src/client.cc index 3bb6efc7..2ad7022a 100644 --- a/src/client.cc +++ b/src/client.cc @@ -24,10 +24,14 @@ Client::Client(std::unique_ptr&& ui, { context().set_client(*this); context().set_window(*m_window); + + m_window->options().register_watcher(*this); + m_ui->set_ui_options(m_window->options()["ui_options"].get()); } Client::~Client() { + m_window->options().unregister_watcher(*this); } void Client::handle_available_input() @@ -77,13 +81,19 @@ DisplayLine Client::generate_mode_line() const void Client::change_buffer(Buffer& buffer) { auto& client_manager = ClientManager::instance(); + m_window->options().unregister_watcher(*this); client_manager.add_free_window(std::move(m_window), std::move(context().selections())); WindowAndSelections ws = client_manager.get_free_window(buffer); + m_window = std::move(ws.window); + m_window->options().register_watcher(*this); + m_ui->set_ui_options(m_window->options()["ui_options"].get()); + context().m_selections = std::move(ws.selections); context().set_window(*m_window); m_window->set_dimensions(ui().dimensions()); + m_window->hooks().run_hook("WinDisplay", buffer.name(), context()); } @@ -181,4 +191,10 @@ const String& Client::get_env_var(const String& name) const return it->second; } +void Client::on_option_changed(const Option& option) +{ + if (option.name() == "ui_options") + m_ui->set_ui_options(option.get()); +} + } diff --git a/src/client.hh b/src/client.hh index a7f2d1ed..6da499a3 100644 --- a/src/client.hh +++ b/src/client.hh @@ -7,6 +7,7 @@ #include "safe_ptr.hh" #include "string.hh" #include "utils.hh" +#include "option_manager.hh" namespace Kakoune { @@ -14,7 +15,7 @@ namespace Kakoune class UserInterface; class Window; -class Client : public SafeCountable +class Client : public SafeCountable, public OptionManagerWatcher { public: Client(std::unique_ptr&& ui, @@ -24,6 +25,8 @@ public: String name); ~Client(); + Client(Client&&) = delete; + // handle all the keys currently available in the user interface void handle_available_input(); @@ -47,6 +50,8 @@ public: const String& get_env_var(const String& name) const; private: + void on_option_changed(const Option& option) override; + DisplayLine generate_mode_line() const; std::unique_ptr m_ui; diff --git a/src/main.cc b/src/main.cc index 056d55ee..d9236d8d 100644 --- a/src/main.cc +++ b/src/main.cc @@ -229,6 +229,9 @@ void register_options() reg.declare_option("autoreload", "autoreload buffer when a filesystem modification is detected", Ask); + reg.declare_option("ui_options", + "options passed to UI as a string map", + UserInterface::Options()); } void create_local_client(const String& init_command) diff --git a/src/ncurses.cc b/src/ncurses.cc index 0e4a84a0..c479d66a 100644 --- a/src/ncurses.cc +++ b/src/ncurses.cc @@ -25,8 +25,6 @@ namespace Kakoune { -constexpr bool status_on_top = true; - using std::min; using std::max; @@ -337,7 +335,7 @@ void NCursesUI::draw(const DisplayBuffer& display_buffer, { check_resize(); - LineCount line_index = status_on_top ? 1 : 0; + LineCount line_index = m_status_on_top ? 1 : 0; for (const DisplayLine& line : display_buffer.lines()) { wmove(m_window, (int)line_index, 0); @@ -347,14 +345,14 @@ void NCursesUI::draw(const DisplayBuffer& display_buffer, } set_face(m_window, { Colors::Blue, Colors::Default }); - while (line_index < m_dimensions.line + (status_on_top ? 1 : 0)) + while (line_index < m_dimensions.line + (m_status_on_top ? 1 : 0)) { wmove(m_window, (int)line_index++, 0); wclrtoeol(m_window); waddch(m_window, '~'); } - int status_line_pos = status_on_top ? 0 : (int)m_dimensions.line; + int status_line_pos = m_status_on_top ? 0 : (int)m_dimensions.line; wmove(m_window, status_line_pos, 0); wclrtoeol(m_window); draw_line(status_line, 0); @@ -551,8 +549,8 @@ void NCursesUI::menu_show(memoryview items, m_menu_bg = bg; if (style == MenuStyle::Prompt) - anchor = CharCoord{status_on_top ? 0_line : m_dimensions.line, 0}; - else if (status_on_top) + anchor = CharCoord{m_status_on_top ? 0_line : m_dimensions.line, 0}; + else if (m_status_on_top) anchor.line += 1; CharCoord maxsize = window_size(stdscr); @@ -797,10 +795,10 @@ void NCursesUI::info_show(StringView title, StringView content, { fancy_info_box = make_info_box(title, content, m_dimensions.column); info_box = fancy_info_box; - anchor = CharCoord{status_on_top ? 0 : m_dimensions.line, + anchor = CharCoord{m_status_on_top ? 0 : m_dimensions.line, m_dimensions.column-1}; } - else if (status_on_top) + else if (m_status_on_top) anchor.line += 1; CharCoord size = compute_needed_size(info_box); @@ -853,4 +851,11 @@ void NCursesUI::abort() endwin(); } +void NCursesUI::set_ui_options(const Options& options) +{ + auto it = options.find("ncurses_status_on_top"); + if (it != options.end()) + m_status_on_top = it->second == "yes" or it->second == "true"; +} + } diff --git a/src/ncurses.hh b/src/ncurses.hh index 8674f075..3f59b05c 100644 --- a/src/ncurses.hh +++ b/src/ncurses.hh @@ -41,6 +41,8 @@ public: void set_input_callback(InputCallback callback) override; + void set_ui_options(const Options& options) override; + CharCoord dimensions() override; static void abort(); @@ -68,6 +70,8 @@ private: FDWatcher m_stdin_watcher; InputCallback m_input_callback; + bool m_status_on_top = false; + bool m_dirty = false; }; diff --git a/src/remote.cc b/src/remote.cc index b7a4b4cf..9b8bab66 100644 --- a/src/remote.cc +++ b/src/remote.cc @@ -26,7 +26,8 @@ enum class RemoteUIMsg InfoShow, InfoHide, Draw, - Refresh + Refresh, + SetOptions }; struct socket_error{}; @@ -271,6 +272,8 @@ public: void set_input_callback(InputCallback callback) override; + void set_ui_options(const Options& options) override; + private: FDWatcher m_socket_watcher; CharCoord m_dimensions; @@ -357,6 +360,13 @@ void RemoteUI::refresh() msg.write(RemoteUIMsg::Refresh); } +void RemoteUI::set_ui_options(const Options& options) +{ + Message msg(m_socket_watcher.fd()); + msg.write(RemoteUIMsg::SetOptions); + msg.write(options); +} + static const Key::Modifiers resize_modifier = (Key::Modifiers)0x80; bool RemoteUI::is_key_available() @@ -508,6 +518,9 @@ void RemoteClient::process_next_message() case RemoteUIMsg::Refresh: m_ui->refresh(); break; + case RemoteUIMsg::SetOptions: + m_ui->set_ui_options(read_map(socket)); + break; } } diff --git a/src/user_interface.hh b/src/user_interface.hh index 4f959544..dc415967 100644 --- a/src/user_interface.hh +++ b/src/user_interface.hh @@ -6,6 +6,8 @@ #include "memoryview.hh" #include "safe_ptr.hh" +#include + namespace Kakoune { @@ -57,6 +59,9 @@ public: virtual void refresh() = 0; virtual void set_input_callback(InputCallback callback) = 0; + + using Options = std::unordered_map; + virtual void set_ui_options(const Options& options) = 0; }; }