1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 16:37:35 +00:00

LibLine: Unify history reading, prefer File over DeprecatedFile

This commit is contained in:
Ben Wiederhake 2023-05-19 18:10:15 +02:00 committed by Jelle Raaijmakers
parent 64a2a63df6
commit f93ee3142d
2 changed files with 37 additions and 28 deletions

View file

@ -18,7 +18,6 @@
#include <AK/Utf32View.h> #include <AK/Utf32View.h>
#include <AK/Utf8View.h> #include <AK/Utf8View.h>
#include <LibCore/ConfigFile.h> #include <LibCore/ConfigFile.h>
#include <LibCore/DeprecatedFile.h>
#include <LibCore/Event.h> #include <LibCore/Event.h>
#include <LibCore/EventLoop.h> #include <LibCore/EventLoop.h>
#include <LibCore/Notifier.h> #include <LibCore/Notifier.h>
@ -249,26 +248,33 @@ void Editor::add_to_history(DeprecatedString const& line)
m_history_dirty = true; m_history_dirty = true;
} }
bool Editor::load_history(DeprecatedString const& path) ErrorOr<Vector<Editor::HistoryEntry>> Editor::try_load_history(StringView path)
{ {
auto history_file_or_error = Core::File::open(path, Core::File::OpenMode::Read); auto history_file = TRY(Core::File::open(path, Core::File::OpenMode::Read));
if (history_file_or_error.is_error()) auto data = TRY(history_file->read_until_eof());
return false; auto hist = StringView { data };
auto data_or_error = history_file_or_error.value()->read_until_eof(); Vector<HistoryEntry> history;
if (data_or_error.is_error())
return false;
auto hist = StringView { data_or_error.value() };
for (auto& str : hist.split_view("\n\n"sv)) { for (auto& str : hist.split_view("\n\n"sv)) {
auto it = str.find("::"sv).value_or(0); auto it = str.find("::"sv).value_or(0);
auto time = str.substring_view(0, it).to_int<time_t>().value_or(0); auto time = str.substring_view(0, it).to_int<time_t>().value_or(0);
auto string = str.substring_view(it == 0 ? it : it + 2); auto string = str.substring_view(it == 0 ? it : it + 2);
m_history.append({ string, time }); history.append({ string, time });
} }
return true; return history;
} }
template<typename It0, typename It1, typename OutputT, typename MapperT, typename LessThan> bool Editor::load_history(DeprecatedString const& path)
static void merge(It0&& begin0, It0 const& end0, It1&& begin1, It1 const& end1, OutputT& output, MapperT left_mapper, LessThan less_than) {
auto history_or_error = try_load_history(path);
if (history_or_error.is_error())
return false;
auto maybe_error = m_history.try_extend(history_or_error.release_value());
auto okay = !maybe_error.is_error();
return okay;
}
template<typename It0, typename It1, typename OutputT, typename LessThan>
static void merge(It0&& begin0, It0 const& end0, It1&& begin1, It1 const& end1, OutputT& output, LessThan less_than)
{ {
for (;;) { for (;;) {
if (begin0 == end0 && begin1 == end1) if (begin0 == end0 && begin1 == end1)
@ -282,7 +288,7 @@ static void merge(It0&& begin0, It0 const& end0, It1&& begin1, It1 const& end1,
continue; continue;
} }
auto&& left = left_mapper(*begin0); auto&& left = *begin0;
if (left.entry.is_whitespace()) { if (left.entry.is_whitespace()) {
++begin0; ++begin0;
continue; continue;
@ -311,30 +317,32 @@ static void merge(It0&& begin0, It0 const& end0, It1&& begin1, It1 const& end1,
bool Editor::save_history(DeprecatedString const& path) bool Editor::save_history(DeprecatedString const& path)
{ {
// Note: Use a dummy entry to simplify merging.
Vector<HistoryEntry> final_history { { "", 0 } }; Vector<HistoryEntry> final_history { { "", 0 } };
{ {
auto file_or_error = Core::DeprecatedFile::open(path, Core::OpenMode::ReadWrite, 0600); auto history_or_error = try_load_history(path);
if (file_or_error.is_error()) if (history_or_error.is_error())
return false; return false;
auto file = file_or_error.release_value(); Vector<HistoryEntry> old_history = history_or_error.release_value();
merge( merge(
file->line_begin(), file->line_end(), m_history.begin(), m_history.end(), final_history, old_history.begin(), old_history.end(),
[](StringView str) { m_history.begin(), m_history.end(),
auto it = str.find("::"sv).value_or(0); final_history,
auto time = str.substring_view(0, it).to_int<time_t>().value_or(0);
auto string = str.substring_view(it == 0 ? it : it + 2);
return HistoryEntry { string, time };
},
[](HistoryEntry const& left, HistoryEntry const& right) { return left.timestamp < right.timestamp; }); [](HistoryEntry const& left, HistoryEntry const& right) { return left.timestamp < right.timestamp; });
} }
auto file_or_error = Core::DeprecatedFile::open(path, Core::OpenMode::WriteOnly, 0600); auto file_or_error = Core::File::open(path, Core::File::OpenMode::Write, 0600);
if (file_or_error.is_error()) if (file_or_error.is_error())
return false; return false;
auto file = file_or_error.release_value(); auto file = file_or_error.release_value();
final_history.take_first(); // Skip the dummy entry:
for (auto const& entry : final_history) for (auto iter = final_history.begin() + 1; iter != final_history.end(); ++iter) {
file->write(DeprecatedString::formatted("{}::{}\n\n", entry.timestamp, entry.entry)); auto const& entry = *iter;
auto buffer = DeprecatedString::formatted("{}::{}\n\n", entry.timestamp, entry.entry);
auto maybe_error = file->write_until_depleted(buffer.bytes());
if (maybe_error.is_error())
return false;
}
m_history_dirty = false; m_history_dirty = false;
return true; return true;

View file

@ -475,6 +475,7 @@ private:
size_t m_history_cursor { 0 }; size_t m_history_cursor { 0 };
size_t m_history_capacity { 1024 }; size_t m_history_capacity { 1024 };
bool m_history_dirty { false }; bool m_history_dirty { false };
static ErrorOr<Vector<HistoryEntry>> try_load_history(StringView path);
enum class InputState { enum class InputState {
Free, Free,