editor: Add "Save file as..." and error dialogs
Some checks failed
Build and test / build (push) Failing after 1m32s

This commit is contained in:
apio 2024-09-19 18:27:16 +02:00
parent fd2fe16538
commit fd26f40938
Signed by: apio
GPG Key ID: B8A7D06E42258954
3 changed files with 46 additions and 13 deletions

View File

@ -10,10 +10,12 @@
#include "EditorWidget.h" #include "EditorWidget.h"
#include <ctype.h> #include <ctype.h>
#include <luna/PathParser.h> #include <luna/PathParser.h>
#include <luna/RefString.h>
#include <luna/Utf8.h> #include <luna/Utf8.h>
#include <os/File.h> #include <os/File.h>
#include <os/FileSystem.h> #include <os/FileSystem.h>
#include <ui/App.h> #include <ui/App.h>
#include <ui/Dialog.h>
EditorWidget::EditorWidget(SharedPtr<ui::Font> font) : ui::TextInput(), m_font(font) EditorWidget::EditorWidget(SharedPtr<ui::Font> font) : ui::TextInput(), m_font(font)
{ {
@ -27,7 +29,8 @@ Result<void> EditorWidget::load_file(const os::Path& path)
if (!rc.has_error() && !S_ISREG(st.st_mode)) if (!rc.has_error() && !S_ISREG(st.st_mode))
{ {
os::eprintln("editor: not loading %s as it is not a regular file", path.name().chars()); auto message = TRY(RefString::format("%s is not a regular file", path.name().chars()));
ui::Dialog::show_message("Error", message.view());
return {}; return {};
} }
@ -41,9 +44,9 @@ Result<void> EditorWidget::load_file(const os::Path& path)
m_cursor = m_data.size(); m_cursor = m_data.size();
m_path = path; m_path = TRY(String::from_string_view(path.name()));
auto basename = TRY(PathParser::basename(m_path.name())); auto basename = TRY(PathParser::basename(m_path.view()));
String title = TRY(String::format("Text Editor - %s"_sv, basename.chars())); String title = TRY(String::format("Text Editor - %s"_sv, basename.chars()));
window()->set_title(title.view()); window()->set_title(title.view());
@ -126,15 +129,38 @@ Result<ui::EventResult> EditorWidget::handle_key_event(const ui::KeyEventRequest
return ui::EventResult::DidHandle; return ui::EventResult::DidHandle;
} }
Result<void> EditorWidget::save_file_as()
{
ui::Dialog::show_input_dialog(
"Save file as...", "Please enter the path to save this file to:", [this](StringView path) {
m_path = String::from_string_view(path).release_value();
auto rc = save_file();
if (rc.has_error())
{
os::eprintln("Failed to save file %s: %s", m_path.chars(), rc.error_string());
ui::Dialog::show_message("Error", "Failed to save file");
}
else
{
auto basename = PathParser::basename(m_path.view()).release_value();
String title = String::format("Text Editor - %s"_sv, basename.chars()).release_value();
window()->set_title(title.view());
}
});
return {};
}
Result<void> EditorWidget::save_file() Result<void> EditorWidget::save_file()
{ {
if (m_path.is_empty_path()) if (m_path.is_empty())
{ {
os::eprintln("editor: no file to save buffer to!"); TRY(save_file_as());
return err(ENOENT); return err(ENOENT);
} }
auto file = TRY(os::File::open(m_path, os::File::WriteOnly)); auto file = TRY(os::File::open_or_create(m_path.view(), os::File::WriteOnly));
return file->write(m_data); return file->write(m_data);
} }

View File

@ -21,14 +21,15 @@ class EditorWidget : public ui::TextInput
Result<void> load_file(const os::Path& path); Result<void> load_file(const os::Path& path);
Result<void> save_file(); Result<void> save_file();
Result<void> save_file_as();
Result<ui::EventResult> handle_key_event(const ui::KeyEventRequest& request) override; Result<ui::EventResult> handle_key_event(const ui::KeyEventRequest& request) override;
Result<void> draw(ui::Canvas& canvas) override; Result<void> draw(ui::Canvas& canvas) override;
os::Path& path() os::Path path()
{ {
return m_path; return m_path.view();
} }
private: private:
@ -41,7 +42,7 @@ class EditorWidget : public ui::TextInput
}; };
Vector<Line> m_lines; Vector<Line> m_lines;
os::Path m_path { AT_FDCWD }; String m_path;
Result<void> recalculate_lines(); Result<void> recalculate_lines();
void recalculate_cursor_position(); void recalculate_cursor_position();

View File

@ -11,6 +11,7 @@
#include <os/ArgumentParser.h> #include <os/ArgumentParser.h>
#include <os/File.h> #include <os/File.h>
#include <ui/App.h> #include <ui/App.h>
#include <ui/Dialog.h>
Result<int> luna_main(int argc, char** argv) Result<int> luna_main(int argc, char** argv)
{ {
@ -32,15 +33,20 @@ Result<int> luna_main(int argc, char** argv)
auto* editor = TRY(make<EditorWidget>(ui::Font::default_font())); auto* editor = TRY(make<EditorWidget>(ui::Font::default_font()));
window->set_main_widget(*editor); window->set_main_widget(*editor);
if (!path.is_empty()) TRY(editor->load_file(path)); if (!path.is_empty()) editor->load_file(path);
TRY(window->add_keyboard_shortcut({ moon::K_CH26, ui::Mod_Ctrl }, true, [&](ui::Shortcut) { TRY(window->add_keyboard_shortcut({ moon::K_CH26, ui::Mod_Ctrl }, true, [&](ui::Shortcut) {
auto result = editor->save_file(); auto result = editor->save_file();
if (result.has_error()) os::eprintln("editor: failed to save file: %s", result.error_string()); if (result.has_error())
else {
os::println("editor: buffer saved to %s successfully", editor->path().name().chars()); os::eprintln("Failed to save file %s: %s", editor->path().name().chars(), result.error_string());
ui::Dialog::show_message("Error", "Failed to save file");
}
})); }));
TRY(window->add_keyboard_shortcut({ moon::K_CH26, ui::Mod_Ctrl | ui::Mod_Shift }, true,
[&](ui::Shortcut) { editor->save_file_as(); }));
window->draw(); window->draw();
return app.run(); return app.run();