From 8285102b6dc8cda99dd94ceab41d8ff223afd671 Mon Sep 17 00:00:00 2001 From: Oriko Date: Fri, 13 Mar 2020 15:38:21 +0200 Subject: [PATCH] HackStudio: Add Javascript projects --- Base/home/anon/js/javascript.files | 2 ++ DevTools/HackStudio/Project.cpp | 55 ++++++++++++++++++++++++++++-- DevTools/HackStudio/Project.h | 9 +++++ DevTools/HackStudio/main.cpp | 46 ++++++++++++++++++++----- 4 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 Base/home/anon/js/javascript.files diff --git a/Base/home/anon/js/javascript.files b/Base/home/anon/js/javascript.files new file mode 100644 index 0000000000..16d6fe4a77 --- /dev/null +++ b/Base/home/anon/js/javascript.files @@ -0,0 +1,2 @@ +javascript.files +*.js diff --git a/DevTools/HackStudio/Project.cpp b/DevTools/HackStudio/Project.cpp index 4678d43acf..ba79af4507 100644 --- a/DevTools/HackStudio/Project.cpp +++ b/DevTools/HackStudio/Project.cpp @@ -28,10 +28,12 @@ #include #include #include +#include #include #include #include #include +#include struct Project::ProjectTreeNode : public RefCounted { enum class Type { @@ -194,15 +196,53 @@ OwnPtr Project::load_from_file(const String& path) if (!file->open(Core::File::ReadOnly)) return nullptr; + auto type = ProjectType::Cpp; Vector files; + + auto add_glob = [&](String path) { + auto split = path.split('*', true); + for (auto& item : split) { + dbg() << item; + } + ASSERT(split.size() == 2); + auto cwd = getcwd(nullptr, 0); + Core::DirIterator it(cwd, Core::DirIterator::Flags::SkipParentAndBaseDir); + while (it.has_next()) { + auto path = it.next_path(); + if (!split[0].is_empty() && !path.starts_with(split[0])) + continue; + + if (!split[1].is_empty() && !path.ends_with(split[1])) + continue; + + files.append(path); + } + }; + for (;;) { auto line = file->read_line(1024); if (line.is_null()) break; - files.append(String::copy(line, Chomp)); + + auto path = String::copy(line, Chomp); + if (path.contains("*")) + add_glob(path); + else + files.append(path); } - return OwnPtr(new Project(path, move(files))); + for (auto& file : files) { + if (file.ends_with(".js")) { + type = ProjectType::Javascript; + break; + } + } + + quick_sort(files); + + auto project = OwnPtr(new Project(path, move(files))); + project->m_type = type; + return project; } bool Project::add_file(const String& filename) @@ -249,6 +289,17 @@ ProjectFile* Project::get_file(const String& filename) return nullptr; } +String Project::default_file() const +{ + if (m_type == ProjectType::Cpp) + return "main.cpp"; + + if (m_files.size() > 0) + return m_files.first().name(); + + ASSERT_NOT_REACHED(); +} + void Project::rebuild_tree() { auto root = adopt(*new ProjectTreeNode); diff --git a/DevTools/HackStudio/Project.h b/DevTools/HackStudio/Project.h index 2077c36d2d..9551ad2ffd 100644 --- a/DevTools/HackStudio/Project.h +++ b/DevTools/HackStudio/Project.h @@ -33,6 +33,12 @@ #include #include +enum class ProjectType { + Unknown, + Cpp, + Javascript +}; + class Project { AK_MAKE_NONCOPYABLE(Project) AK_MAKE_NONMOVABLE(Project) @@ -47,7 +53,9 @@ public: ProjectFile* get_file(const String& filename); + ProjectType type() const { return m_type; } GUI::Model& model() { return *m_model; } + String default_file() const; template void for_each_text_file(Callback callback) const @@ -65,6 +73,7 @@ private: const ProjectTreeNode& root_node() const { return *m_root_node; } void rebuild_tree(); + ProjectType m_type { ProjectType::Unknown }; String m_name; String m_path; RefPtr m_model; diff --git a/DevTools/HackStudio/main.cpp b/DevTools/HackStudio/main.cpp index d3e04044fa..3f987dd4f9 100644 --- a/DevTools/HackStudio/main.cpp +++ b/DevTools/HackStudio/main.cpp @@ -119,6 +119,7 @@ Editor& current_editor() static void build(TerminalWrapper&); static void run(TerminalWrapper&); +void open_project(String); void open_file(const String&); bool make_is_available(); @@ -158,12 +159,7 @@ int main(int argc, char** argv) if (!make_is_available()) GUI::MessageBox::show("The 'make' command is not available. You probably want to install the binutils, gcc, and make ports from the root of the Serenity repository.", "Error", GUI::MessageBox::Type::Error, GUI::MessageBox::InputType::OK, g_window); - if (chdir("/home/anon/little") < 0) { - perror("chdir"); - return 1; - } - g_project = Project::load_from_file("little.files"); - ASSERT(g_project); + open_project("/home/anon/js/javascript.files"); auto& toolbar = widget.add(); @@ -396,6 +392,15 @@ int main(int argc, char** argv) update_actions(); }); + auto open_action = GUI::Action::create("Open Project", { Mod_Ctrl | Mod_Shift, Key_O }, Gfx::Bitmap::load_from_file("/res/icons/16x16/open.png"), [&](auto&) { + auto open_path = GUI::FilePicker::get_open_filepath(); + if (!open_path.has_value()) + return; + open_project(open_path.value()); + open_file(g_project->default_file()); + update_actions(); + }); + auto save_action = GUI::Action::create("Save", { Mod_Ctrl, Key_S }, Gfx::Bitmap::load_from_file("/res/icons/16x16/save.png"), [&](auto&) { if (g_currently_open_file.is_empty()) return; @@ -456,7 +461,9 @@ int main(int argc, char** argv) auto menubar = make(); auto app_menu = GUI::Menu::construct("HackStudio"); + app_menu->add_action(open_action); app_menu->add_action(save_action); + app_menu->add_separator(); app_menu->add_action(GUI::CommonActions::make_quit_action([&](auto&) { app.quit(); })); @@ -532,7 +539,7 @@ int main(int argc, char** argv) g_open_file = open_file; - open_file("main.cpp"); + open_file(g_project->default_file()); update_actions(); return app.exec(); @@ -540,12 +547,33 @@ int main(int argc, char** argv) void build(TerminalWrapper& wrapper) { - wrapper.run_command("make"); + if (g_project->type() == ProjectType::Javascript && g_currently_open_file.ends_with(".js")) + wrapper.run_command(String::format("js -A %s", g_currently_open_file.characters())); + else + wrapper.run_command("make"); } void run(TerminalWrapper& wrapper) { - wrapper.run_command("make run"); + if (g_project->type() == ProjectType::Javascript && g_currently_open_file.ends_with(".js")) + wrapper.run_command(String::format("js %s", g_currently_open_file.characters())); + else + wrapper.run_command("make run"); +} + +void open_project(String filename) +{ + FileSystemPath path(filename); + if (chdir(path.dirname().characters()) < 0) { + perror("chdir"); + exit(1); + } + g_project = Project::load_from_file(filename); + ASSERT(g_project); + if (g_project_tree_view) { + g_project_tree_view->set_model(g_project->model()); + g_project_tree_view->update(); + } } void open_file(const String& filename)