diff --git a/src/client.cc b/src/client.cc index aabe52eb..08ae32c7 100644 --- a/src/client.cc +++ b/src/client.cc @@ -182,7 +182,7 @@ public: if (key == Key(Key::Modifiers::Control, 'm')) { context().ui().menu_hide(); - context().ui().print_status(DisplayLine{}); + context().print_status(DisplayLine{}); reset_normal_mode(); int selected = m_selected - m_choices.begin(); m_callback(selected, MenuEvent::Validate, context()); @@ -195,7 +195,7 @@ public: m_edit_filter = false; m_filter = boost::regex(".*"); m_filter_editor.reset(""); - context().ui().print_status(DisplayLine{}); + context().print_status(DisplayLine{}); } else { @@ -246,7 +246,7 @@ public: { auto display_line = m_filter_editor.build_display_line(); display_line.insert(display_line.begin(), { "filter:"_str, get_color("Prompt") }); - context().ui().print_status(display_line); + context().print_status(display_line); } } @@ -320,7 +320,7 @@ public: history.erase(it); history.push_back(line); } - context().ui().print_status(DisplayLine{}); + context().print_status(DisplayLine{}); context().ui().menu_hide(); reset_normal_mode(); // call callback after reset_normal_mode so that callback @@ -330,7 +330,7 @@ public: } else if (key == Key::Escape or key == Key { Key::Modifiers::Control, 'c' }) { - context().ui().print_status(DisplayLine{}); + context().print_status(DisplayLine{}); context().ui().menu_hide(); reset_normal_mode(); m_callback(line, PromptEvent::Abort, context()); @@ -453,7 +453,7 @@ private: { auto display_line = m_line_editor.build_display_line(); display_line.insert(display_line.begin(), { m_prompt, m_prompt_colors }); - context().ui().print_status(display_line); + context().print_status(display_line); } PromptCallback m_callback; @@ -1019,4 +1019,47 @@ void Client::stop_recording() m_recording_reg = 0; } +void Client::print_status(DisplayLine status_line) +{ + m_status_line = std::move(status_line); + m_context.window().forget_timestamp(); +} + +static DisplayLine generate_mode_line(Client& client) +{ + auto& context = client.context(); + auto pos = context.editor().main_selection().last(); + auto col = context.buffer()[pos.line].char_count_to(pos.column); + + std::ostringstream oss; + oss << context.buffer().display_name() + << " " << (int)pos.line+1 << ":" << (int)col+1; + if (context.buffer().is_modified()) + oss << " [+]"; + if (context.client().is_recording()) + oss << " [recording]"; + if (context.buffer().flags() & Buffer::Flags::New) + oss << " [new file]"; + oss << " [" << context.editor().selections().size() << " sel]"; + if (context.editor().is_editing()) + oss << " [insert]"; + oss << " - " << client.name(); + return { oss.str(), get_color("StatusLine") }; +} + +void Client::redraw_ifn() +{ + if (m_context.window().timestamp() != m_context.buffer().timestamp()) + { + DisplayCoord dimensions = m_context.ui().dimensions(); + if (dimensions == DisplayCoord{0,0}) + return; + m_context.window().set_dimensions(dimensions); + m_context.window().update_display_buffer();; + + m_context.ui().draw(m_context.window().display_buffer(), + m_status_line, generate_mode_line(*this)); + } +} + } diff --git a/src/client.hh b/src/client.hh index ef1a178d..eec3bbd9 100644 --- a/src/client.hh +++ b/src/client.hh @@ -8,6 +8,7 @@ #include "keys.hh" #include "string.hh" #include "utils.hh" +#include "display_buffer.hh" namespace Kakoune { @@ -78,6 +79,10 @@ public: const String& name() const { return m_name; } void set_name(String name) { m_name = std::move(name); } + void print_status(DisplayLine status_line); + + void redraw_ifn(); + UserInterface& ui() const { return *m_ui; } private: Context m_context; @@ -87,6 +92,7 @@ private: std::vector> m_mode_trash; String m_name; + DisplayLine m_status_line; using Insertion = std::pair>; Insertion m_last_insert = {InsertMode::Insert, {}}; diff --git a/src/client_manager.cc b/src/client_manager.cc index c50d313e..3dd93697 100644 --- a/src/client_manager.cc +++ b/src/client_manager.cc @@ -151,45 +151,10 @@ Client& ClientManager::get_client(const String& name) throw runtime_error("no client named: " + name); } -static DisplayLine generate_status_line(Client& client) -{ - auto& context = client.context(); - auto pos = context.editor().main_selection().last(); - auto col = context.buffer()[pos.line].char_count_to(pos.column); - - std::ostringstream oss; - oss << context.buffer().display_name() - << " " << (int)pos.line+1 << ":" << (int)col+1; - if (context.buffer().is_modified()) - oss << " [+]"; - if (context.client().is_recording()) - oss << " [recording]"; - if (context.buffer().flags() & Buffer::Flags::New) - oss << " [new file]"; - oss << " [" << context.editor().selections().size() << " sel]"; - if (context.editor().is_editing()) - oss << " [insert]"; - oss << " - " << client.name(); - return { oss.str(), get_color("StatusLine") }; -} - void ClientManager::redraw_clients() const { for (auto& client : m_clients) - { - Context& context = client->context(); - if (context.window().timestamp() != context.buffer().timestamp()) - { - DisplayCoord dimensions = context.ui().dimensions(); - if (dimensions == DisplayCoord{0,0}) - return; - context.window().set_dimensions(dimensions); - context.window().update_display_buffer();; - - context.ui().draw(context.window().display_buffer(), - generate_status_line(*client)); - } - } + client->redraw_ifn(); } } diff --git a/src/commands.cc b/src/commands.cc index 0f772dd8..bad02704 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -540,8 +540,6 @@ void declare_option(CommandParameters params, Context& context) class DraftUI : public UserInterface { public: - void print_status(const DisplayLine&) override {} - void menu_show(memoryview, DisplayCoord, ColorPair, ColorPair, MenuStyle) override {} void menu_select(int) override {} void menu_hide() override {} @@ -549,7 +547,7 @@ public: void info_show(const String&, DisplayCoord, ColorPair, MenuStyle) override {} void info_hide() override {} - void draw(const DisplayBuffer&, const DisplayLine&) override {} + void draw(const DisplayBuffer&, const DisplayLine&, const DisplayLine&) override {} DisplayCoord dimensions() override { return {0,0}; } bool is_key_available() override { return false; } Key get_key() override { return 'a'; } @@ -571,8 +569,7 @@ void context_wrap(CommandParameters params, Context& context, Func func) { Editor& editor = real_context.editor(); Client client(std::unique_ptr(new DraftUI()), editor, - real_context.has_client() ? - real_context.client().name() : ""); + real_context.has_client() ? real_context.client().name() : ""); DynamicSelectionList sels{editor.buffer(), editor.selections()}; auto restore_sels = on_scope_end([&]{ editor.select(sels); }); func(parser, client.context()); diff --git a/src/context.cc b/src/context.cc index cf00bc0a..f81d2b9e 100644 --- a/src/context.cc +++ b/src/context.cc @@ -75,10 +75,10 @@ HookManager& Context::hooks() const return GlobalHooks::instance(); } -void Context::print_status(const DisplayLine& status) const +void Context::print_status(DisplayLine status) const { - if (has_ui()) - ui().print_status(status); + if (has_client()) + client().print_status(std::move(status)); } void Context::push_jump() diff --git a/src/context.hh b/src/context.hh index fe7a4021..736d78e8 100644 --- a/src/context.hh +++ b/src/context.hh @@ -49,7 +49,7 @@ struct Context OptionManager& options() const; HookManager& hooks() const; - void print_status(const DisplayLine& status) const; + void print_status(DisplayLine status) const; void push_jump(); const DynamicSelectionList& jump_forward(); diff --git a/src/ncurses.cc b/src/ncurses.cc index f5fcb973..8d29a62e 100644 --- a/src/ncurses.cc +++ b/src/ncurses.cc @@ -240,6 +240,7 @@ void NCursesUI::draw_line(const DisplayLine& line, CharCount col_index) const } void NCursesUI::draw(const DisplayBuffer& display_buffer, + const DisplayLine& status_line, const DisplayLine& mode_line) { LineCount line_index = 0; @@ -265,10 +266,10 @@ void NCursesUI::draw(const DisplayBuffer& display_buffer, move((int)m_dimensions.line, 0); clrtoeol(); - draw_line(m_status_line, 0); + draw_line(status_line, 0); CharCount status_len = mode_line.length(); // only draw mode_line if it does not overlap one status line - if (m_dimensions.column - m_status_line.length() > status_len + 1) + if (m_dimensions.column - status_line.length() > status_len + 1) { CharCount col = m_dimensions.column - status_len; move((int)m_dimensions.line, (int)col); @@ -358,15 +359,6 @@ Key NCursesUI::get_key() return Key::Invalid; } -void NCursesUI::print_status(const DisplayLine& status) -{ - m_status_line = status; - move((int)m_dimensions.line, 0); - clrtoeol(); - draw_line(status, 0); - redraw(); -} - void NCursesUI::draw_menu() { // menu show may have not created the window if it did not fit. diff --git a/src/ncurses.hh b/src/ncurses.hh index 2cdcd06d..47463eb7 100644 --- a/src/ncurses.hh +++ b/src/ncurses.hh @@ -20,8 +20,8 @@ public: NCursesUI& operator=(const NCursesUI&) = delete; void draw(const DisplayBuffer& display_buffer, + const DisplayLine& status_line, const DisplayLine& mode_line) override; - void print_status(const DisplayLine& status) override; bool is_key_available() override; Key get_key() override; @@ -49,8 +49,6 @@ private: DisplayCoord m_dimensions; void update_dimensions(); - DisplayLine m_status_line; - NCursesWin* m_menu_win = nullptr; std::vector m_choices; ColorPair m_menu_fg; diff --git a/src/remote.cc b/src/remote.cc index 39542a0b..cb55bb8e 100644 --- a/src/remote.cc +++ b/src/remote.cc @@ -20,7 +20,6 @@ namespace Kakoune enum class RemoteUIMsg { - PrintStatus, MenuShow, MenuSelect, MenuHide, @@ -217,8 +216,6 @@ public: RemoteUI(int socket); ~RemoteUI(); - void print_status(const DisplayLine& status) override; - void menu_show(memoryview choices, DisplayCoord anchor, ColorPair fg, ColorPair bg, MenuStyle style) override; @@ -230,6 +227,7 @@ public: void info_hide() override; void draw(const DisplayBuffer& display_buffer, + const DisplayLine& status_line, const DisplayLine& mode_line) override; bool is_key_available() override; @@ -257,13 +255,6 @@ RemoteUI::~RemoteUI() close(m_socket_watcher.fd()); } -void RemoteUI::print_status(const DisplayLine& status) -{ - Message msg(m_socket_watcher.fd()); - msg.write(RemoteUIMsg::PrintStatus); - msg.write(status); -} - void RemoteUI::menu_show(memoryview choices, DisplayCoord anchor, ColorPair fg, ColorPair bg, MenuStyle style) @@ -308,11 +299,13 @@ void RemoteUI::info_hide() } void RemoteUI::draw(const DisplayBuffer& display_buffer, + const DisplayLine& status_line, const DisplayLine& mode_line) { Message msg(m_socket_watcher.fd()); msg.write(RemoteUIMsg::Draw); msg.write(display_buffer); + msg.write(status_line); msg.write(mode_line); } @@ -385,12 +378,6 @@ void RemoteClient::process_next_message() RemoteUIMsg msg = read(socket); switch (msg) { - case RemoteUIMsg::PrintStatus: - { - auto status = read(socket); - m_ui->print_status(status); - break; - } case RemoteUIMsg::MenuShow: { auto choices = read_vector(socket); @@ -422,8 +409,9 @@ void RemoteClient::process_next_message() case RemoteUIMsg::Draw: { auto display_buffer = read(socket); + auto status_line = read(socket); auto mode_line = read(socket); - m_ui->draw(display_buffer, mode_line); + m_ui->draw(display_buffer, status_line, mode_line); break; } } diff --git a/src/user_interface.hh b/src/user_interface.hh index 2e2b6171..0f9c3a35 100644 --- a/src/user_interface.hh +++ b/src/user_interface.hh @@ -26,7 +26,6 @@ class UserInterface : public SafeCountable { public: virtual ~UserInterface() {} - virtual void print_status(const DisplayLine& status) = 0; virtual void menu_show(memoryview choices, DisplayCoord anchor, ColorPair fg, ColorPair bg, @@ -39,6 +38,7 @@ public: virtual void info_hide() = 0; virtual void draw(const DisplayBuffer& display_buffer, + const DisplayLine& status_line, const DisplayLine& mode_line) = 0; virtual DisplayCoord dimensions() = 0; virtual bool is_key_available() = 0;