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:
parent
6658d15741
commit
224f73d72a
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
})}
|
||||
{}
|
||||
|
|
Loading…
Reference in New Issue
Block a user