Browse Source

HackStudio: Add Javascript projects

Oriko 5 years ago
parent
commit
8285102b6d

+ 2 - 0
Base/home/anon/js/javascript.files

@@ -0,0 +1,2 @@
+javascript.files
+*.js

+ 53 - 2
DevTools/HackStudio/Project.cpp

@@ -28,10 +28,12 @@
 #include <AK/FileSystemPath.h>
 #include <AK/QuickSort.h>
 #include <AK/StringBuilder.h>
+#include <LibCore/DirIterator.h>
 #include <LibCore/File.h>
 #include <stdio.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <unistd.h>
 
 struct Project::ProjectTreeNode : public RefCounted<ProjectTreeNode> {
     enum class Type {
@@ -194,15 +196,53 @@ OwnPtr<Project> Project::load_from_file(const String& path)
     if (!file->open(Core::File::ReadOnly))
         return nullptr;
 
+    auto type = ProjectType::Cpp;
     Vector<String> 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);

+ 9 - 0
DevTools/HackStudio/Project.h

@@ -33,6 +33,12 @@
 #include <LibGUI/Icon.h>
 #include <LibGUI/Model.h>
 
+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<typename Callback>
     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<GUI::Model> m_model;

+ 37 - 9
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<GUI::ToolBar>();
 
@@ -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<GUI::MenuBar>();
     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)