mirror of
https://github.com/RGBCube/serenity
synced 2025-05-28 14:25:06 +00:00
HackStudio: Add Javascript projects
This commit is contained in:
parent
792a709765
commit
8285102b6d
4 changed files with 101 additions and 11 deletions
2
Base/home/anon/js/javascript.files
Normal file
2
Base/home/anon/js/javascript.files
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
javascript.files
|
||||||
|
*.js
|
|
@ -28,10 +28,12 @@
|
||||||
#include <AK/FileSystemPath.h>
|
#include <AK/FileSystemPath.h>
|
||||||
#include <AK/QuickSort.h>
|
#include <AK/QuickSort.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
|
#include <LibCore/DirIterator.h>
|
||||||
#include <LibCore/File.h>
|
#include <LibCore/File.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
struct Project::ProjectTreeNode : public RefCounted<ProjectTreeNode> {
|
struct Project::ProjectTreeNode : public RefCounted<ProjectTreeNode> {
|
||||||
enum class Type {
|
enum class Type {
|
||||||
|
@ -194,15 +196,53 @@ OwnPtr<Project> Project::load_from_file(const String& path)
|
||||||
if (!file->open(Core::File::ReadOnly))
|
if (!file->open(Core::File::ReadOnly))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
auto type = ProjectType::Cpp;
|
||||||
Vector<String> files;
|
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 (;;) {
|
for (;;) {
|
||||||
auto line = file->read_line(1024);
|
auto line = file->read_line(1024);
|
||||||
if (line.is_null())
|
if (line.is_null())
|
||||||
break;
|
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)
|
bool Project::add_file(const String& filename)
|
||||||
|
@ -249,6 +289,17 @@ ProjectFile* Project::get_file(const String& filename)
|
||||||
return nullptr;
|
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()
|
void Project::rebuild_tree()
|
||||||
{
|
{
|
||||||
auto root = adopt(*new ProjectTreeNode);
|
auto root = adopt(*new ProjectTreeNode);
|
||||||
|
|
|
@ -33,6 +33,12 @@
|
||||||
#include <LibGUI/Icon.h>
|
#include <LibGUI/Icon.h>
|
||||||
#include <LibGUI/Model.h>
|
#include <LibGUI/Model.h>
|
||||||
|
|
||||||
|
enum class ProjectType {
|
||||||
|
Unknown,
|
||||||
|
Cpp,
|
||||||
|
Javascript
|
||||||
|
};
|
||||||
|
|
||||||
class Project {
|
class Project {
|
||||||
AK_MAKE_NONCOPYABLE(Project)
|
AK_MAKE_NONCOPYABLE(Project)
|
||||||
AK_MAKE_NONMOVABLE(Project)
|
AK_MAKE_NONMOVABLE(Project)
|
||||||
|
@ -47,7 +53,9 @@ public:
|
||||||
|
|
||||||
ProjectFile* get_file(const String& filename);
|
ProjectFile* get_file(const String& filename);
|
||||||
|
|
||||||
|
ProjectType type() const { return m_type; }
|
||||||
GUI::Model& model() { return *m_model; }
|
GUI::Model& model() { return *m_model; }
|
||||||
|
String default_file() const;
|
||||||
|
|
||||||
template<typename Callback>
|
template<typename Callback>
|
||||||
void for_each_text_file(Callback callback) const
|
void for_each_text_file(Callback callback) const
|
||||||
|
@ -65,6 +73,7 @@ private:
|
||||||
const ProjectTreeNode& root_node() const { return *m_root_node; }
|
const ProjectTreeNode& root_node() const { return *m_root_node; }
|
||||||
void rebuild_tree();
|
void rebuild_tree();
|
||||||
|
|
||||||
|
ProjectType m_type { ProjectType::Unknown };
|
||||||
String m_name;
|
String m_name;
|
||||||
String m_path;
|
String m_path;
|
||||||
RefPtr<GUI::Model> m_model;
|
RefPtr<GUI::Model> m_model;
|
||||||
|
|
|
@ -119,6 +119,7 @@ Editor& current_editor()
|
||||||
|
|
||||||
static void build(TerminalWrapper&);
|
static void build(TerminalWrapper&);
|
||||||
static void run(TerminalWrapper&);
|
static void run(TerminalWrapper&);
|
||||||
|
void open_project(String);
|
||||||
void open_file(const String&);
|
void open_file(const String&);
|
||||||
bool make_is_available();
|
bool make_is_available();
|
||||||
|
|
||||||
|
@ -158,12 +159,7 @@ int main(int argc, char** argv)
|
||||||
if (!make_is_available())
|
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);
|
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) {
|
open_project("/home/anon/js/javascript.files");
|
||||||
perror("chdir");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
g_project = Project::load_from_file("little.files");
|
|
||||||
ASSERT(g_project);
|
|
||||||
|
|
||||||
auto& toolbar = widget.add<GUI::ToolBar>();
|
auto& toolbar = widget.add<GUI::ToolBar>();
|
||||||
|
|
||||||
|
@ -396,6 +392,15 @@ int main(int argc, char** argv)
|
||||||
update_actions();
|
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&) {
|
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())
|
if (g_currently_open_file.is_empty())
|
||||||
return;
|
return;
|
||||||
|
@ -456,7 +461,9 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
auto menubar = make<GUI::MenuBar>();
|
auto menubar = make<GUI::MenuBar>();
|
||||||
auto app_menu = GUI::Menu::construct("HackStudio");
|
auto app_menu = GUI::Menu::construct("HackStudio");
|
||||||
|
app_menu->add_action(open_action);
|
||||||
app_menu->add_action(save_action);
|
app_menu->add_action(save_action);
|
||||||
|
app_menu->add_separator();
|
||||||
app_menu->add_action(GUI::CommonActions::make_quit_action([&](auto&) {
|
app_menu->add_action(GUI::CommonActions::make_quit_action([&](auto&) {
|
||||||
app.quit();
|
app.quit();
|
||||||
}));
|
}));
|
||||||
|
@ -532,7 +539,7 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
g_open_file = open_file;
|
g_open_file = open_file;
|
||||||
|
|
||||||
open_file("main.cpp");
|
open_file(g_project->default_file());
|
||||||
|
|
||||||
update_actions();
|
update_actions();
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
@ -540,12 +547,33 @@ int main(int argc, char** argv)
|
||||||
|
|
||||||
void build(TerminalWrapper& wrapper)
|
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)
|
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)
|
void open_file(const String& filename)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue