Cleanup and refactor externally modified buffer reloading

* Correctly hide the reload dialog in every client.
* Correctly handle buffer being deleted.
This commit is contained in:
Maxime Coste 2015-02-12 14:55:02 +00:00
parent 6658d15741
commit 224f73d72a
4 changed files with 71 additions and 41 deletions

View File

@ -125,6 +125,9 @@ DisplayLine Client::generate_mode_line() const
void Client::change_buffer(Buffer& buffer)
{
if (m_buffer_reload_dialog_opened)
close_buffer_reload_dialog();
auto& client_manager = ClientManager::instance();
m_window->options().unregister_watcher(*this);
client_manager.add_free_window(std::move(m_window),
@ -166,21 +169,58 @@ void Client::redraw_ifn()
context().ui().refresh();
}
static void reload_buffer(Context& context, StringView filename)
void Client::reload_buffer()
{
CharCoord view_pos = context.window().position();
ByteCoord cursor_pos = context.selections().main().cursor();
Buffer* buf = create_buffer_from_file(filename);
if (not buf)
return;
context.change_buffer(*buf);
context.selections() = SelectionList{ *buf, buf->clamp(cursor_pos)};
context.window().set_position(view_pos);
context.print_status({ "'" + buf->display_name() + "' reloaded",
get_face("Information") });
auto& buffer = context().buffer();
kak_assert(buffer.flags() & Buffer::Flags::File);
CharCoord view_pos = context().window().position();
ByteCoord cursor_pos = context().selections().main().cursor();
Buffer* buf = create_buffer_from_file(buffer.name());
kak_assert(buf == &buffer);
context().selections() = SelectionList{buffer, buffer.clamp(cursor_pos)};
context().window().set_position(view_pos);
context().print_status({ "'" + buffer.display_name() + "' reloaded",
get_face("Information") });
}
void Client::check_buffer_fs_timestamp()
void Client::on_buffer_reload_key(Key key)
{
auto& buffer = context().buffer();
if (key == 'y' or key == ctrl('m'))
reload_buffer();
else if (key == 'n' or key == Key::Escape)
{
// reread timestamp in case the file was modified again
buffer.set_fs_timestamp(get_fs_timestamp(buffer.name()));
print_status({ "'" + buffer.display_name() + "' kept",
get_face("Information") });
}
else
{
print_status({ "'" + key_to_str(key) + "' is not a valid choice",
get_face("Error") });
m_input_handler.on_next_key(KeymapMode::None, [this](Key key, Context&){ on_buffer_reload_key(key); });
return;
}
for (auto& client : ClientManager::instance())
{
if (&client->context().buffer() == &buffer and
client->m_buffer_reload_dialog_opened)
client->close_buffer_reload_dialog();
}
}
void Client::close_buffer_reload_dialog()
{
kak_assert(m_buffer_reload_dialog_opened);
m_buffer_reload_dialog_opened = false;
m_ui->info_hide();
m_input_handler.reset_normal_mode();
}
void Client::check_if_buffer_needs_reloading()
{
Buffer& buffer = context().buffer();
auto reload = context().options()["autoreload"].get<YesNoAsk>();
@ -196,36 +236,14 @@ void Client::check_buffer_fs_timestamp()
m_ui->info_show(
"reload '" + buffer.display_name() + "' ?",
"'" + buffer.display_name() + "' was modified externally\n"
"press <ret>, r or y to reload, <esc>, k or n to keep",
"press <ret> or y to reload, <esc> or n to keep",
CharCoord{}, get_face("Information"), InfoStyle::Prompt);
m_input_handler.on_next_key(KeymapMode::None,
[this, filename](Key key, Context& context) {
m_ui->info_hide();
Buffer* buf = BufferManager::instance().get_buffer_ifp(filename);
// buffer got deleted while waiting for the key, do nothing
if (not buf)
return;
if (key == 'r' or key == 'y' or key == ctrl('m'))
reload_buffer(context, filename);
else if (key == 'k' or key == 'n' or key == Key::Escape)
{
// reread timestamp in case the file was modified again
buf->set_fs_timestamp(get_fs_timestamp(filename));
print_status({ "'" + buf->display_name() + "' kept",
get_face("Information") });
}
else
{
print_status({ "'" + key_to_str(key) + "' is not a valid choice",
get_face("Error") });
check_buffer_fs_timestamp();
}
});
m_buffer_reload_dialog_opened = true;
m_input_handler.on_next_key(KeymapMode::None, [this](Key key, Context&){ on_buffer_reload_key(key); });
}
else
reload_buffer(context(), filename);
reload_buffer();
}
StringView Client::get_env_var(const String& name) const

View File

@ -40,7 +40,7 @@ public:
UserInterface& ui() const { return *m_ui; }
Window& window() const { return *m_window; }
void check_buffer_fs_timestamp();
void check_if_buffer_needs_reloading();
Context& context() { return m_input_handler.context(); }
const Context& context() const { return m_input_handler.context(); }
@ -55,6 +55,10 @@ public:
private:
void on_option_changed(const Option& option) override;
void on_buffer_reload_key(Key key);
void close_buffer_reload_dialog();
void reload_buffer();
Optional<Key> get_next_key(EventMode mode);
DisplayLine generate_mode_line() const;
@ -71,6 +75,8 @@ private:
DisplayLine m_mode_line;
Vector<Key, MemoryDomain::Client> m_pending_keys;
bool m_buffer_reload_dialog_opened = false;
};
}

View File

@ -42,13 +42,19 @@ public:
bool validate_client_name(StringView name) const;
void remove_client(Client& client);
using ClientList = Vector<std::unique_ptr<Client>, MemoryDomain::Client>;
using iterator = ClientList::const_iterator;
iterator begin() const { return m_clients.begin(); }
iterator end() const { return m_clients.end(); }
CandidateList complete_client_name(StringView name,
ByteCount cursor_pos = -1) const;
private:
String generate_name() const;
Vector<std::unique_ptr<Client>> m_clients;
ClientList m_clients;
Vector<WindowAndSelections, MemoryDomain::Client> m_free_windows;
};

View File

@ -64,7 +64,7 @@ public:
Timer::Callback() : Timer::Callback([this](Timer& timer) {
if (not context().has_client())
return;
context().client().check_buffer_fs_timestamp();
context().client().check_if_buffer_needs_reloading();
timer.set_next_date(Clock::now() + fs_check_timeout);
})}
{}